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

Split connection management away from exporter #1369

Merged
merged 13 commits into from
Dec 21, 2020

Conversation

krnowak
Copy link
Member

@krnowak krnowak commented Nov 25, 2020

This commits adds an ConnectionManager interface, which the exporter
will use to connect to the collector and send both metrics and traces
to it. That way, the Exporter type is free from dealing with any
connection/protocol details, as this business is taken over by the
implementations of the ConnectionManager interface.

The gRPC code from the exporter is moved into the implementation of
ConnectionManager. Currently it only maintains a single connection,
just as the Exporter used to do.

With the split, most of the Exporter options became actually gRPC
connection manager's options. Currently the only option that remained
to be Exporter's is about setting the export kind selector.

@codecov
Copy link

codecov bot commented Nov 25, 2020

Codecov Report

Merging #1369 (1123f58) into master (add9d93) will increase coverage by 0.2%.
The diff coverage is 88.0%.

Impacted file tree graph

@@           Coverage Diff            @@
##           master   #1369     +/-   ##
========================================
+ Coverage    78.1%   78.3%   +0.2%     
========================================
  Files         123     125      +2     
  Lines        6252    6259      +7     
========================================
+ Hits         4885    4904     +19     
+ Misses       1119    1111      -8     
+ Partials      248     244      -4     
Impacted Files Coverage Δ
exporters/otlp/options.go 100.0% <ø> (+44.4%) ⬆️
exporters/otlp/otlp.go 90.9% <75.0%> (+7.3%) ⬆️
exporters/otlp/grpcoptions.go 87.5% <87.5%> (ø)
exporters/otlp/grpcdriver.go 90.1% <90.1%> (ø)
exporters/otlp/grpcconnection.go 85.9% <100.0%> (ø)
sdk/trace/batch_span_processor.go 78.4% <0.0%> (-2.0%) ⬇️
exporters/otlp/internal/transform/metric.go 80.6% <0.0%> (+0.5%) ⬆️

Copy link
Contributor

@MrAlias MrAlias left a comment

Choose a reason for hiding this comment

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

I like the overall design of adding the ConnectionManager interface. I'm interested to know what you think about leaving the transform functionality in the exporter though and keeping the new ConnectionManager interface focused on transport.

exporters/otlp/connectionmanager.go Outdated Show resolved Hide resolved
exporters/otlp/connectionmanager.go Outdated Show resolved Hide resolved
exporters/otlp/grpcsingle.go Outdated Show resolved Hide resolved
exporters/otlp/grpcsingle.go Outdated Show resolved Hide resolved
@krnowak
Copy link
Member Author

krnowak commented Nov 30, 2020

@dashpole: Thanks for the review. I'll reply to both your issues here.

NewGRPCSingleConnectionManager implies there is something other than "Single" that we would want to add in the future. Would we want to make the "other" thing we want to add an option instead of a new function, and shorten this to NewGRPCConnectionManager? That would be fine so long as the options would still apply, which I think they should.

I think it is slightly easier to use if this takes ...options instead of a configuration since it doesn't require defining the configuration in a separate statement.

I.E.

func NewGRPCSingleConnectionManager(opts ...GRPCConnectionOption) ConnectionManager

The follow-up PR would introduce the NewGRPCMultiConnectionManager function, hence the Single in the name. The new function would create a connection manager that maintains separate connections for tracing and metrics. Both connections could be configured separately, which leads to a problem with the opts ...GRPCConnectionOption part: I don't see an elegant solution to configuring traces and metrics connection separately with the opts ...GRPCConnectionOption interface, other than duplicating all the options into WithTracesFoo and WithMetricsFoo. So for NewGRPCMultiConnectionManager I went with:

type MultiConnectionConfig struct {
	Traces GRPCConnectionConfig
	Metrics GRPCConnectionConfig
}

func NewGRPCMultiConnectionManager(cfg MultiConnectionConfig) ConnectionManager { … }

So for NewGRPCSingleConnectionManager I went with taking GRPCConnectionConfig as a parameter, instead of opts ...GRPCConnectionConfig for consistency. This is rather inconsistent with the rest of the project, which is something that #536 seeks to resolve.

@dashpole
Copy link
Contributor

This is rather inconsistent with the rest of the project, which is something that #536 seeks to resolve.

Got it. Thanks for linking the issue.

The follow-up PR would introduce the NewGRPCMultiConnectionManager function

That makes sense. This is part of #1121, right?

If there are eventually going to be multiple types of exporters (not just grpc), it might make sense to make a more generic single vs multi connection manager that isn't grpc-specific. For example (with the current naming):

type MultiConnectionConfig struct {
	Traces ConnectionManager
	Metrics ConnectionManager
}

func NewMultiConnectionManager(cfg MultiConnectionConfig) ConnectionManager { … }

@krnowak
Copy link
Member Author

krnowak commented Dec 1, 2020

This is rather inconsistent with the rest of the project, which is something that #536 seeks to resolve.

Got it. Thanks for linking the issue.

The follow-up PR would introduce the NewGRPCMultiConnectionManager function

That makes sense. This is part of #1121, right?

Yes.

If there are eventually going to be multiple types of exporters (not just grpc), it might make sense to make a more generic single vs multi connection manager that isn't grpc-specific. For example (with the current naming):

type MultiConnectionConfig struct {
	Traces ConnectionManager
	Metrics ConnectionManager
}

func NewMultiConnectionManager(cfg MultiConnectionConfig) ConnectionManager { … }

I got something like that already: krnowak@f8c2ec8, but maybe your variant with the config is actually better, because you spell you explicitly which manager goes for tracing and which for metrics. So thanks for the idea and we'll see how it fares during the review when it appears in another PR.

@krnowak
Copy link
Member Author

krnowak commented Dec 1, 2020

Updated.

exporters/otlp/protocoldriver.go Show resolved Hide resolved
@krnowak
Copy link
Member Author

krnowak commented Dec 2, 2020

Updated. Added some tests to increase the coverage a bit (increasing coverage for error conditions is rather annoying). And fixed one or two races.

@krnowak krnowak force-pushed the otlp-exporter-3 branch 2 times, most recently from 03c6837 to 6e272f9 Compare December 7, 2020 20:05
@krnowak
Copy link
Member Author

krnowak commented Dec 9, 2020

Before merging it, I'd like to discuss one thing at the Golang SIG meeting first.

Copy link
Contributor

@seanschade seanschade left a comment

Choose a reason for hiding this comment

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

Just added a recommendation for a NewGRPCConnectionConfig function.

exporters/otlp/grpcoptions.go Outdated Show resolved Hide resolved
@MrAlias
Copy link
Contributor

MrAlias commented Dec 10, 2020

From the SIG meeting, we are going to not add a single/multiple gRPC connection driver. Instead going to progress to just using the driver interface to support multiple protocols for now.

@jmacd
Copy link
Contributor

jmacd commented Dec 11, 2020

This looks good to me, independent of the single- vs multi-driver question, simply for taking us one step closer to an OTLP/HTTP exporter. 😀

@krnowak
Copy link
Member Author

krnowak commented Dec 11, 2020

Rebased and updated. Simplified the gRPC driver a bit.

@krnowak krnowak force-pushed the otlp-exporter-3 branch 2 times, most recently from ce9d867 to 671792a Compare December 16, 2020 17:37
@krnowak
Copy link
Member Author

krnowak commented Dec 16, 2020

Updated to fix a conflict in changelog. Updated some tests to be a bit less flaky.

@krnowak krnowak force-pushed the otlp-exporter-3 branch 2 times, most recently from ed98136 to 3af8ec7 Compare December 18, 2020 13:17
This commits adds a ProtocolDriver interface, which the exporter
will use to connect to the collector and send both metrics and traces
to it. That way, the Exporter type is free from dealing with any
connection/protocol details, as this business is taken over by the
implementations of the ProtocolDriver interface.

The gRPC code from the exporter is moved into the implementation of
ProtocolDriver. Currently it only maintains a single connection,
just as the Exporter used to do.

With the split, most of the Exporter options became actually gRPC
connection manager's options. Currently the only option that remained
to be Exporter's is about setting the export kind selector.
The disconnected channel can be used for sending by multiple
goroutines (for example, by metric controller and span processor), so
this channel should not be closed at all. Dropping this line closes a
race between closing a channel and sending to it.
The callbacks never return an error, so drop the return type from it.
The client may change as a result on reconnection in background, so
guard against a racy access.
The config type was exported earlier to have a consistent way of
configuring the driver, when also the multiple connection driver would
appear. Since we are not going to add a multiple connection driver,
pass the options directly to the driver constructor. Also shorten the
name of the constructor to `NewGRPCDriver`.
The common code was supposed to be shared between single connection
driver and multiple connection driver, but since the latter won't be
happening, it makes no sense to keep the not-so-common code in a
separate file. Also drop some abstraction too.
Sometimes CI has it's better moments, so it's blazing fast and manages
to finish shutting the exporter down within the 1 microsecond timeout.
One millisecond is quite short, and I was getting failures locally or
in CI:

go test ./... + race in ./exporters/otlp
2020/12/14 18:27:54 rpc error: code = Canceled desc = context canceled
2020/12/14 18:27:54 context deadline exceeded
--- FAIL: TestNewExporter_withMultipleAttributeTypes (0.37s)
    otlp_integration_test.go:541: resource span count: got 0, want 1
FAIL
FAIL	go.opentelemetry.io/otel/exporters/otlp	5.278s

or

go test ./... + coverage in ./exporters/otlp
2020/12/14 17:41:16 rpc error: code = Canceled desc = context canceled
2020/12/14 17:41:16 exporter disconnected
--- FAIL: TestNewExporter_endToEnd (1.53s)
    --- FAIL: TestNewExporter_endToEnd/WithCompressor (0.41s)
        otlp_integration_test.go:246: span counts: got 3, want 4
2020/12/14 17:41:18 context canceled
FAIL
coverage: 35.3% of statements in ./...
FAIL	go.opentelemetry.io/otel/exporters/otlp	4.753s
This is to make sure that all batched spans are actually flushed
before closing the exporter.
Copy link
Contributor

@MrAlias MrAlias left a comment

Choose a reason for hiding this comment

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

Awesome work 👍

@MrAlias MrAlias merged commit 3521526 into open-telemetry:master Dec 21, 2020
@krnowak krnowak deleted the otlp-exporter-3 branch December 21, 2020 22:39
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.

5 participants