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

Make ITransport top-level abstraction for sending events to Sentry. #1118

Merged

Conversation

maciejwalkowiak
Copy link
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Flip the relation between AsyncConnection and ITransport and make BlockingHttpTransport use HttpConnection, making it possible to provide alternative transport implementations not bound to use thread pool.

💡 Motivation and Context

In order to provide non blocking transport, transport itself has to be responsible for managing threads (not the AsyncConnection).

💚 How did you test it?

Unit & integration tests.

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • All tests passing
  • No breaking changes

🔮 Next steps

Flip the relation between `AsyncConnection` and `ITransport` and make `BlockingHttpTransport` use `HttpConnection`, making it possible to provide alternative transport implementations not bound to use thread pool.
@maciejwalkowiak
Copy link
Contributor Author

@marandaneto, as a next step - I believe we should create an interface ITransportFactory and put it on SentryOptions, instead of ITransfer itself. Currently, since transport is set on SentryOptions, but transport itself also likely depends on SentryOptions, it may be difficult for users to provide custom transport implementations.

@codecov-io
Copy link

codecov-io commented Dec 16, 2020

Codecov Report

Merging #1118 (6bda502) into gh-1097-rate-limiter (3296e31) will decrease coverage by 0.43%.
The diff coverage is 89.41%.

Impacted file tree graph

@@                    Coverage Diff                     @@
##             gh-1097-rate-limiter    #1118      +/-   ##
==========================================================
- Coverage                   74.09%   73.66%   -0.44%     
+ Complexity                   1591     1569      -22     
==========================================================
  Files                         164      164              
  Lines                        5633     5609      -24     
  Branches                      576      572       -4     
==========================================================
- Hits                         4174     4132      -42     
- Misses                       1178     1185       +7     
- Partials                      281      292      +11     
Impacted Files Coverage Δ Complexity Δ
...c/main/java/io/sentry/transport/NoOpTransport.java 0.00% <0.00%> (-50.00%) 0.00 <0.00> (-2.00)
.../io/sentry/transport/QueuedThreadPoolExecutor.java 80.95% <ø> (ø) 7.00 <0.00> (ø)
...main/java/io/sentry/transport/StdoutTransport.java 77.77% <ø> (+11.11%) 2.00 <0.00> (ø)
.../src/main/java/io/sentry/NoOpTransportFactory.java 66.66% <66.66%> (ø) 2.00 <2.00> (?)
sentry/src/main/java/io/sentry/SentryOptions.java 83.90% <75.00%> (+0.06%) 106.00 <2.00> (ø)
...n/java/io/sentry/transport/AsyncHttpTransport.java 61.85% <82.14%> (ø) 8.00 <5.00> (?)
.../main/java/io/sentry/transport/HttpConnection.java 75.00% <94.11%> (ø) 18.00 <0.00> (?)
...src/main/java/io/sentry/log4j2/SentryAppender.java 82.71% <100.00%> (ø) 19.00 <0.00> (ø)
...rc/main/java/io/sentry/logback/SentryAppender.java 87.01% <100.00%> (-1.30%) 21.00 <1.00> (-1.00)
...io/sentry/spring/boot/SentryAutoConfiguration.java 93.61% <100.00%> (ø) 1.00 <0.00> (ø)
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3296e31...6bda502. Read the comment docs.

envelopeCache.discard(envelope);
}
} else {
executor.submit(new EnvelopeSender(filteredEnvelope, hint, currentEnvelopeCache));
Copy link
Member

Choose a reason for hiding this comment

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

I think the name BlockingHttpTransport is misleading since it gives the impression the interface is going to block until for the event submission, which isnt' the case.

We're scheduling the event through the executor here.

Maybe we can use another name?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah I kinda agree, not sure about a suitable name though.

SingleThreadHttpTransport?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can be also AsyncHttpTransport. It is async, but blocking.

@ApiStatus.NonExtendable // only not final because of testing
@ApiStatus.Internal
public class HttpTransport implements ITransport {
class HttpConnection {
Copy link
Contributor

Choose a reason for hiding this comment

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

is the HttpConnection reusable for the NIO implementation as well? just trying to understand why we have the BlockingHttpTransport + HttpConnection, I do get their difference, but what would be the advantage of it right now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to split the responsibilities - and I agree that the split is not perfect. I tried to create decorators like EnvelopeCachingHttpTransport and RateLimitingHttpTransport but since send returns void it's also not possible.

HttpConnection is package private, to give us flexibility of refactoring later without breaking users' code.

Copy link
Contributor

Choose a reason for hiding this comment

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

sounds good to me

@marandaneto
Copy link
Contributor

do we need a changelog? how do we communicate the breaking changes later on?

@maciejwalkowiak
Copy link
Contributor Author

@marandaneto @bruno-garcia I need this PR reviewed.

final class AsyncHttpTransportFactory implements TransportFactory {

@Override
public ITransport create(final @NotNull SentryOptions options) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we add throws IllegalArgumentException in the method signature?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we should not, what's the reasonable way to handle this exception here anyways?

Copy link
Contributor

Choose a reason for hiding this comment

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

if we handle it down its fine, I was just curious cus the TransportFactory now is the way to go for custom transports right

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't handle it, the exception is propagated to the very top and in the end Sentry init will fail.

This PR is a PR to another branch, so once whole package is there we can take a look at it again.

Copy link
Contributor

@marandaneto marandaneto left a comment

Choose a reason for hiding this comment

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

few missing jetbrains annotations but other than that LGTM.

I didn't find a plugin that fails the build if annotations are missing, but it'd be nice to write a custom linter for that, so I don't need to be the human linter here :D

I am only picky about that cus it's nicer when writing Kotlin code.

import org.jetbrains.annotations.NotNull;

/** Creates instances of {@link ITransport}. */
public interface TransportFactory {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we do ITransportFactory?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have mixed feelings about putting I in the front of names for interfaces, but I will just follow your preference. Tell me :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

no feelings or preferences here, but see ITransport, so ideally, we do a single way, either all of them or none of them.
chose which ones to rename :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let it be ITransportFactory.

@maciejwalkowiak maciejwalkowiak merged commit 43b3c1f into gh-1097-rate-limiter Dec 22, 2020
@maciejwalkowiak maciejwalkowiak deleted the gh-1097-transport-connection-flip branch December 22, 2020 11:30
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.

4 participants