Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tracing: Support dynamically loading tracing libraries. #2252

Merged
merged 38 commits into from
Feb 28, 2018

Conversation

rnburn
Copy link
Contributor

@rnburn rnburn commented Dec 21, 2017

Signed-off-by: Ryan Burn ryan.burn@gmail.com

Description:

This PR adds support for dynamically loading tracers into Envoy. It will allow authors of OpenTracing compliant tracers to support envoy without requiring envoy to bake their tracers into its build. Tracing libraries can be enabled by adding a section like this to envoy's configuration:

  tracing:
    http:
      name: envoy.dynamic.ot
      config:
        library: /path/to/tracing/library
        config: {
          ....
        }

With this change, Envoy will be able to use Jaeger's new C++ tracing library. Some features this will allow that aren't available when using Jaeger as a collector for Zipkin:

While it might also make sense sometime in the future to offer a version of Jaeger or other tracers built into Envoy, decoupled plug-in support will allow for quicker on-boarding of tracers and more experimentation in the area without making Envoy's external dependencies become unmanageable.

Notes:

  • One challenge with using dynamically loaded libraries in Envoy is that the standard c++ library is statically compiled in with the option -static-libstdc++. If plugin libraries are linked to the libstdc++ in a standard way, this will create problems as two versions of the standard library will be loaded and calls to their functions from the plugin will be intermingled between them, breaking many of the standard library functions. The approach I took with Jaeger was to have it also use -static-libstdc++ and then use an export map to ensure that it's version of the standard library is used without any intermingling (see dsohowto for background on the approach). It does mean that there will be multiple copies of libstdc++ running, but from what I've heard this can be made to work. Another approach could be to add a config option to link libstdc++ dynamically.
  • This depends on Add support for dynamic loading. opentracing/opentracing-cpp#45 being merged in to opentracing-cpp, but I wanted to get a PR in early to get feedback on the approach in case we need to make changes to that PR.

Risk Level: Medium

Testing:
I have a small example that demoes this functionality using docker and a branch of jaeger.

I also plan to add unit test coverage using a mock tracer library that will be added to opentracing-cpp.

Docs Changes:

envoyproxy/data-plane-api#386

Release Notes:

Included in PR.

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@mattklein123
Copy link
Member

@rnburn this is sweet. Real quick comment (have not reviewed): This is going to need v2 config defined here: https://github.com/envoyproxy/data-plane-api/blob/master/api/trace.proto. (Everything now is v2 first. v1 is optional). Can you do the data-plane-api PR and then work that into this PR?

@mattklein123
Copy link
Member

Also, from a quick scan, this will need tests. You are probably going to have to compile some type of test driver as an .so and load it or something. Not sure what is best.

@rnburn
Copy link
Contributor Author

rnburn commented Dec 22, 2017

Yes, I'm working on a mocktracer library (similar to what's in opentracing-go) that will be distributed as part of opentracing-cpp and can be used to test dynamic loading against.

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@rnburn
Copy link
Contributor Author

rnburn commented Jan 3, 2018

I added a data plane PR to support corresponding v2 options and to document the v1 options.

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@mattklein123 mattklein123 self-assigned this Jan 12, 2018
htuch pushed a commit to envoyproxy/data-plane-api that referenced this pull request Jan 23, 2018
Add options for specifying a tracing library to load dynamically (See also envoyproxy/envoy#2252.)

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@mattklein123
Copy link
Member

@rnburn friendly ping on this. If this won't be completed for a while do you mind if we close for now and reopen when ready?

@rnburn
Copy link
Contributor Author

rnburn commented Jan 25, 2018

Sorry for the delay.

I just added in a mocktracer library implementing the dynamic loading interface to opentracing-cpp (opentracing/opentracing-cpp@359bafe) that I can use to add testing coverage for the dynamic loading code. I plan to do that this week.

If some blocker comes up and I can't finish the PR soon, I'll close it out and reopen.

…amic-tracing

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@rnburn
Copy link
Contributor Author

rnburn commented Jan 25, 2018

Updated to use the configuration changes from envoyproxy/data-plane-api#386. I'm adding in testing coverage next.

@rnburn
Copy link
Contributor Author

rnburn commented Jan 25, 2018

@yurishkuro @isaachier -- are you ok with the build requirements that this method of dynamic loading imposes on the tracing library? Is it a build you could see supporting for Jaeger's C++ client?

Just to summarize: What you need to do is

  1. Link dependencies in statically (including the standard C++ library using the flag -static-libstdc++).
  2. Set up the linker to use an export map so that only Jaeger symbols are exposed.

(I also outlined the approach in this SO post).

@isaachier
Copy link

I think CMake helps with the exports: https://cmake.org/cmake/help/v3.0/module/GenerateExportHeader.html. I can fix the linking issue.

@mattklein123
Copy link
Member

@rnburn re: linking, this is our first foray into dynamic linking which I think we will be doing more of in the future. We can also have a compile option for Envoy which dynamically links if that is preferable for some deployments.

@rnburn
Copy link
Contributor Author

rnburn commented Jan 26, 2018

So I have a library mocktracer that implements the dynamic loading interface and is exposed to bazel.

I'm trying to figure out how to write a cc_test so that mocktracer is a dependency that's not linked in but whose location is passed to the unit test so that it can be dlopen-ed and tested against.

Any suggestions on how to do this? (also asked on SO)

@rnburn
Copy link
Contributor Author

rnburn commented Jan 26, 2018

I found one way to do it: If you list a library in the data attribute for cc_test, then it will be available in the current working directory (albeit in a platform-architecture dependent location); but you can then run the find command to discover the path... not very elegant, but is there a better way?

@mattklein123
Copy link
Member

@jmillikin-stripe @htuch any idea on @rnburn question above?

@htuch
Copy link
Member

htuch commented Jan 26, 2018

See https://github.com/envoyproxy/envoy/blob/master/test/test_common/environment.h#L73; this is how you access the data files. Examples are the SSL cert tests, e.g. https://github.com/envoyproxy/envoy/blob/master/test/common/ssl/BUILD#L11 and https://github.com/envoyproxy/envoy/blob/master/test/common/ssl/ssl_socket_test.cc#L1115. In that example, the "rundir" is from a JSON template, but the first link I provided gives you access to the directory as a simple string.

@rnburn
Copy link
Contributor Author

rnburn commented Jan 26, 2018

The library will show up in runfilesDirectory but the path will be something like _solib_darwin_x86_64/libexternal_Sio_Uopentracing_Ucpp_Smocktracer_Slibmocktracer.so

Is there an environmental variable for the _solib_darwin_x86_64 part of the path?

@htuch
Copy link
Member

htuch commented Jan 26, 2018

Maybe a genrule to cp the source location as given by Bazel into some sane standard location?

@jmillikin-stripe
Copy link
Contributor

For data files with annoying complex paths like that, I've usually seen them passed to tests with the args attribute and a command-line flag. This should work with all test rules:

cc_test(
  name = "my_test",
  srcs = ["my_test.cc"],
  data = ["//important:data"],
  args = ["--some-important-data=$(location //important:data)"],
)

For C++ tests in particular, I think (based on the docs) you can also put the path into a preprocessor macro with copts=['-DIMPORTANT_DATA_PATH="$(location //important:data)"'] or defines=['IMPORTANT_DATA_PATH="$(location //important:data)"']. I've never tried this though.

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@rnburn
Copy link
Contributor Author

rnburn commented Jan 31, 2018

@jmillikin-stripe I tried using $(location ...), but it gives me a relative path that's different from where cc_test puts the library from the data parameter. It's also not accessible from the working directory of the test and runfilesDirectory.

I wanted to at least start to get some testing in, so I went forward with using an ugly find hack for now; but I'll replace it with a better solution if I can find one.

…amic-tracing

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
@rnburn
Copy link
Contributor Author

rnburn commented Feb 26, 2018

I added a TODO for an example; I merged in opentracing/opentracing-cpp#45 and I updated the build so that it no longer points to my fork of opentracing-cpp.

I'm going to put in a few more commits to address #2252 (comment); then I think I should be caught up with everything.

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
alyssawilk
alyssawilk previously approved these changes Feb 27, 2018
@alyssawilk
Copy link
Contributor

code LGTM modulo the two build failures. Clean those up and you're good to go

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
…amic-tracing

Signed-off-by: Ryan Burn <ryan.burn@gmail.com>
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

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

LGTM. @htuch could you take a quick pass on this one before we merge?

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

I've left a couple of comments that can be addressed post-merge optionally.

throw EnvoyException{formatErrorMessage(tracer_maybe.error(), error_message)};
}
tracer_ = std::move(*tracer_maybe);
RELEASE_ASSERT(tracer_ != nullptr);
Copy link
Member

Choose a reason for hiding this comment

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

Why is this RELEASE_ASSERT and not ASSERT?

RELEASE_ASSERT(tracer_ != nullptr);
}

std::string DynamicOpenTracingDriver::formatErrorMessage(std::error_code error_code,
Copy link
Member

Choose a reason for hiding this comment

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

This should probably be in the anonymous namespace, it's not using any state from the instance.


DynamicOpenTracingDriver::DynamicOpenTracingDriver(Stats::Store& stats, const std::string& library,
const std::string& tracer_config)
: OpenTracingDriver{stats} {
Copy link
Member

Choose a reason for hiding this comment

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

Tiny nit: FYI, most of Envoy doesn't use brace style when calling super.

@htuch htuch merged commit da865c3 into envoyproxy:master Feb 28, 2018
Shikugawa pushed a commit to Shikugawa/envoy that referenced this pull request Mar 28, 2020
* test envoy wasm build

* circle cmake

* update circle builder image

* Update envoy-wasm sha to the latest

* pin circle ci bazel version at 0.25.0

* update circle ci commands
jpsim added a commit that referenced this pull request Nov 28, 2022
jpsim added a commit that referenced this pull request Nov 29, 2022
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.

None yet

8 participants