tracing: general tracing support#16049
Conversation
|
cc @mattklein123 I think this simple design can make tracers become protocol-independent. But I don’t know if the community has any opinions? 🤔 |
Signed-off-by: wbpcode <comems@msn.com>
e328a9f to
d78258e
Compare
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
|
It's ready for a first review. @mattklein123 If necessary, I can split this PR into multiple PRs, which can reduce the complexity of review. 😄 |
|
Anyone from @envoyproxy/first-pass-reviewers want to take this? At a quick glance it is in right direction. |
rojkov
left a comment
There was a problem hiding this comment.
Basically this looks very good to me. Just couple of things to clarify.
|
|
||
| /** | ||
| * The way how to apply the custom tag to the span, | ||
| * generally obtain the tag value from the context and attached it to the span. |
There was a problem hiding this comment.
Should it be "generally obtains the tag value from the context and attaches it to the span"?
|
|
||
| absl::string_view RequestHeaderCustomTag::value(const CustomTagContext& ctx) const { | ||
| if (!ctx.request_headers) { | ||
| if (!ctx.tracing_context) { |
There was a problem hiding this comment.
Better make it more explicit
if (ctx.tracing_context != nullptr) {| const envoy::config::core::v3::Metadata* | ||
| MetadataCustomTag::metadata(const CustomTagContext& ctx) const { | ||
| const StreamInfo::StreamInfo& info = ctx.stream_info; | ||
| if (!ctx.stream_info) { |
|
|
||
| private: | ||
| DriverPtr driver_; | ||
| DriverSharedPtr driver_; |
There was a problem hiding this comment.
Whom the driver is shared with? I wonder if collective ownership is needed here.
There was a problem hiding this comment.
Yep. The factory will keep a shared_ptr of OpenCensus driver to ensure its uniqueness. This is a long-standing problem and I hope it can be resolved in the future.
/**
* Create a particular tracer driver implementation. If the implementation is unable to produce
* an tracer driver with the provided parameters, it should throw an EnvoyException in the case
* of general error or a Json::Exception if the json configuration is erroneous. The returned
* pointer should always be valid.
*
* NOTE: Due to the corner case of OpenCensus, who can only support a single tracing
* configuration per entire process, the returned Driver instance is not guaranteed
* to be unique.
* That is why the return type has been changed to std::shared_ptr<> instead of a more
* idiomatic std::unique_ptr<>.
*
* @param config supplies the proto configuration for the HttpTracer
* @param context supplies the factory context
*/
virtual Tracing::DriverSharedPtr createTracerDriver(const Protobuf::Message& config,
TracerFactoryContext& context) PURE;
|
@rojkov Thank you very much for your kind review comments. I will update this PR this weekend. 😃 |
| message TracerProvider { | ||
| // The name of the trace driver to instantiate. The name must match a supported trace driver. | ||
| // See the :ref:`extensions listed in typed_config below <extension_category_envoy.tracers>` for the | ||
| // default list of the trace driver. |
There was a problem hiding this comment.
In other places I see "tracing driver", "tracer driver" in addition to "trace driver" used interchangeably. Can we stick to a single term?
| * protocol requests and provides Tracer Driver with common methods for obtaining and setting the | ||
| * Tracing context. | ||
| */ | ||
| class TracingContext { |
There was a problem hiding this comment.
Better rename the file to tracing_context.h to reflect its content.
source/common/http/header_map_impl.h
Outdated
| HeaderEntryImpl& maybeCreateInline(HeaderEntryImpl** entry, const LowerCaseString& key, | ||
| HeaderString&& value); | ||
| HeaderMap::NonConstGetResult getExisting(const LowerCaseString& key); | ||
| HeaderMap::NonConstGetResult getExisting(const absl::string_view key); |
There was a problem hiding this comment.
Here we change the function's contract by adding a new implicit requirement for a caller that key must be lower case. Can we guarantee that or we don't care about casing now?
There was a problem hiding this comment.
getExisting(const absl::string_view key) is a protected method that be used by get(const LowerCaseString& key) and getTracingContext(const absl::string_view key).
The former is the interface of HeaderMap and can always keep the case constraint. The latter is the interface of TracingContext, which is designed to not care about the case of the key.
When developers use TracingContext based on RequestHeaderMapImpl, they should ensure that the key meets the requirements of RequestHeaderMap (key must be lowercase).
There was a problem hiding this comment.
@rojkov In the design of TracingContext, I hope it is completely protocol-independent, so a simple string_view is used as the key type.
But in actual use, the combination of TracingContext and HeaderMap is not perfect.
In getTracingContext, I must assume that the content of key is a lowercase string. In setTracingContext, I must create a LowCaseString copy of the key.
I am thinking about whether I can directly move LowCaseString to common, and then TracingContext directly uses LowCaseString as the key type.
But I am still struggling with it. Maybe the community can give some opinions. 🤔
There was a problem hiding this comment.
I don't have much experience with non-HTTP tracers and don't know if it's practical to convert to LowerCaseString always :( Will defer to the code owners to decide.
|
|
||
| private: | ||
| DriverPtr driver_; | ||
| DriverSharedPtr driver_; |
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
…xt for case-insensitive key Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
| // Used by ASSERTs to validate internal consistency. E.g. valid HTTP header keys/values should | ||
| // never contain embedded NULLs. | ||
| static inline bool validHeaderString(absl::string_view s) { | ||
| // If you modify this list of illegal embedded characters you will probably |
There was a problem hiding this comment.
drive-by comment: This is HTTP-specific and I think should under an http/ directory rather than under common.
I think I see why you wanted to do this: you wanted to add similar support for tracing that is not dependent on http, but then I think you would want to make the validator be pluggable or something, maybe via a template?
There was a problem hiding this comment.
Thanks.😄 Yes, I want add some similar support for tracing. A simple function pointer may be a good choice. Templates or virtual functions will introduce some type conversion problems, which is completely unnecessary.
The validation logic of validHeaderString should be universal, that is, it does not contain newline characters and does not contain null. We can use it as the default validator.
There was a problem hiding this comment.
I'm not understanding why templates would create type conversion problems. But if you are going to use a function pointer you should use a new-style lambda.
Also you probably want to avoid having include/envoy/common/... reference include/envoy/http/... -- at least in my mind that should be a directed graph.
There was a problem hiding this comment.
I'm not understanding why templates would create type conversion problems. But if you are going to use a function pointer you should use a new-style lambda.
Don't care, I should be wrong in my thinking.
Also you probably want to avoid having include/envoy/common/... reference include/envoy/http/... -- at least in my mind that should be a directed graph.
🤔 I was thinking too. Perhaps we can simply treat validHeaderString as a general validator. It does not have any special HTTP-specific logic, just ensure that the string is an ordinary single-line string that does not contain nulls.
This part will be a new independent PR. When it's ready, I will @ you, thanks 😄 .
There was a problem hiding this comment.
It is based on http char-set, though, isn't it?
The use of a template, or for that matter, a function pointer, lambda, or pure virtual function call, is that you could put the generic impl into common/ and the http-specific variant in http/ and you have a clean separation.
Come to think of it, do you want to always lower-case names for non-http?
There was a problem hiding this comment.
@jmarantz Thank you very much for your patience and suggestions.
If I just want to get a general LowerCaseString implementation, your idea is undoubtedly correct. But this question is somewhat different.
Why I want a common LowerCaseString?
Because using RequestHeaderMapImpl to implement the setTraceContext(absl::string_view)/getTraceContext(absl::string_view) interface, additional overhead will be introduced. We need to convert absl::string_view to lower case and always use copy semantics. So I hope to design a general LowerCaseString and add two overloaded interfaces that use LowerCaseString to TraceContext. In this way, for existing Http Tracer users, the introduction of general tracing will not bring any additional overhead.
Why is it difficult to achieve clean separation?
If I use virtual functions or inheritance solutions, use the base class in the TraceContext interface, such as LowerCaseStringBase. Then when RequestHeaderMapImpl implements the TraceContext interface, it will involve the protocol conversion from LowerCaseStringBase to Http::LowerCaseString (I now have some new ideals to circumvent this problem).
If I use function pointers, then we must use validHeaderString as the default value, because now Http::LowerCaseString has been widely used, we need to reduce the impact on existing code. The problem of using templates is similar to that of function pointers. In other words, LowerCaseString will depend on validHeaderString.
Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com>
| absl::optional<absl::string_view> getTraceContext(const LowerCaseString& key) const override { | ||
| auto result = get(key); | ||
| if (!result.empty()) { | ||
| return result[0]->value().getStringView(); | ||
| } | ||
| return absl::nullopt; | ||
| } | ||
|
|
||
| void setTraceContext(const LowerCaseString& key, absl::string_view value) override { | ||
| setReferenceKey(key, value); | ||
| } |
There was a problem hiding this comment.
We might want to just add an implicit conversion from LowerCaseString to string_view, so you don't need those overloads? Though we might want setTraceContext by reference or copy versions.
There was a problem hiding this comment.
@lizan These overloads are designed to ensure that general tracing does not impose additional performance overhead on existing http tracer users. For example, the overhead of verifying that string_view is a legitimate lower case string.
Without this overload, there is only getTraceContext(absl::string_view key), so when RequestHeaderMapImpl implements this interface, we always have to make sure that the content of the key is a lower case string.
There was a problem hiding this comment.
I agree with the sentiment that this PR needs to be split up. So if necessary, this can be continued in a new PR.
lizan
left a comment
There was a problem hiding this comment.
In general, this PR involves many refactoring that can be split out to other PR so it would be easier to review.
This PR could be split out to four different PRs:
The first PR and fourth PR will involve a large number of file updates, but no logical changes. |
This PR is part of #16049 to support general tracing. Please check #16049 get more details. Commit Message: remove trace drivers' dependency on HttpTracerImpl Additional Description: Now all tracers (zipkin, skywalking, etc.) will depend on HttpTracerImpl, making it difficult for Tracers to be reused by other protocols (Dubbo, Thrift, etc.). The purpose of this PR is to change this dependency. Risk Level: Low (No new logic). Testing: Add. Docs Changes: N/A Release Notes: N/A Signed-off-by: wbpcode <comems@msn.com>
|
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
|
/no-stale |
Signed-off-by: wbpcode <comems@msn.com> Sub-PR of #16049. Check #16049 get more background information. This PR designed a new generic abstraction `TraceContext` to replace `Http::RequestHeaderMap` to provide tracing context to the tracer driver. `Http::RequestHeaderMapImpl` already inherits from TraceContext and implements the relevant interfaces. Next, we just need simply replace `Http::RequestHeaderMap` with `TraceContext` in all tracer drivers implementations. After that, the main body of the entire general tracing system is completed. I'm not sure, whether the replacement step requires a separate PR. Because it does not involve any new logic, but there will be a lot of file changes. Risk Level: Low. Testing: Added. Docs Changes: N/A Release Notes: N/A Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode <comems@msn.com> Sub-PR of envoyproxy#16049. Check envoyproxy#16049 get more background information. This PR designed a new generic abstraction `TraceContext` to replace `Http::RequestHeaderMap` to provide tracing context to the tracer driver. `Http::RequestHeaderMapImpl` already inherits from TraceContext and implements the relevant interfaces. Next, we just need simply replace `Http::RequestHeaderMap` with `TraceContext` in all tracer drivers implementations. After that, the main body of the entire general tracing system is completed. I'm not sure, whether the replacement step requires a separate PR. Because it does not involve any new logic, but there will be a lot of file changes. Risk Level: Low. Testing: Added. Docs Changes: N/A Release Notes: N/A Signed-off-by: wbpcode <comems@msn.com> Signed-off-by: chris.xin <xinchuantao@qq.com>
Sub-PR of #16049. Check #16049 get more background information. This PR is last sub-PR of #16049. It simply replaces `Http::RequestHeaderMap` with general `Tracing::TraceContext` in all tracer drivers implementations. Check #16793 get more info about `Tracing::TraceContext`. After this PR, the main body of the entire general tracing system is completed. Next, we can try to use the new general tracing system in dubbo and thrift. Commit Message: replace RequestHeaderMap in tracers with general TraceContext Risk Level: Low. Testing: N/A. Docs Changes: N/A. Release Notes: N/A. Signed-off-by: wbpcode <comems@msn.com>
|
Check #16244 #16793 #17212
**Finally, thank you @lizan for your patience and help. ** |
Signed-off-by: wbpcode <comems@msn.com> Sub-PR of envoyproxy#16049. Check envoyproxy#16049 get more background information. This PR designed a new generic abstraction `TraceContext` to replace `Http::RequestHeaderMap` to provide tracing context to the tracer driver. `Http::RequestHeaderMapImpl` already inherits from TraceContext and implements the relevant interfaces. Next, we just need simply replace `Http::RequestHeaderMap` with `TraceContext` in all tracer drivers implementations. After that, the main body of the entire general tracing system is completed. I'm not sure, whether the replacement step requires a separate PR. Because it does not involve any new logic, but there will be a lot of file changes. Risk Level: Low. Testing: Added. Docs Changes: N/A Release Notes: N/A Signed-off-by: wbpcode <comems@msn.com>
…roxy#17212) Sub-PR of envoyproxy#16049. Check envoyproxy#16049 get more background information. This PR is last sub-PR of envoyproxy#16049. It simply replaces `Http::RequestHeaderMap` with general `Tracing::TraceContext` in all tracer drivers implementations. Check envoyproxy#16793 get more info about `Tracing::TraceContext`. After this PR, the main body of the entire general tracing system is completed. Next, we can try to use the new general tracing system in dubbo and thrift. Commit Message: replace RequestHeaderMap in tracers with general TraceContext Risk Level: Low. Testing: N/A. Docs Changes: N/A. Release Notes: N/A. Signed-off-by: wbpcode <comems@msn.com>
Signed-off-by: wbpcode comems@msn.com
Commit Message: tracing: general tracing support
Additional Description:
Check: #15784
Current tracing system only has great support to HTTP protocol. Other protocol such as Dubbo Proxy or Thrift Proxy cannot reuse tracers that designed for HTTP protocol.
This PR try to separate tracer implementation and HTTP protocol to make the current tracers protocol-independent.
There are mainly two protocol depentent design in current tracing system.
Http::RequestHeaderMapfor tracing context. Tracing Driver will try to obtain tracing context from downstreamHttp::RequestHeaderMapand create tracing span. Tracing span will inject new context toHttp::RequestHeaderMapto transfer it to upstream.HttpTracerrather then rawDriver.So, this PR design a new abstract class for tracing context to replace
Http::RequestHeaderMap(While other protocols can implement an Http::RequestHeaderMap to directly reuse the existing Tracer, this requires a significant amount of work.):And then, we update tracing driver factory to make it no deps to
HttpTracer:All other code modifications are just to adapt to the above changes.
A more detailed doc:
https://docs.google.com/document/d/1gxk5vfHl-Gt3wiNZ-f46Dwmk2NFiEzFJQugmZmpSXk8/edit?usp=sharing
Risk Level: mid
Testing: [WIP]
Docs Changes: N/A
Release Notes: [WIP]