Skip to content

Conversation

@pchinery
Copy link

As discussed in #941, this is a proposal to make the ITransport configurable, which required to make the interface and some other classes along the path public.

The transport will be wrapped with caching, if configured.

@codecov-commenter
Copy link

codecov-commenter commented Apr 19, 2021

Codecov Report

Merging #944 (c42362b) into main (cacbd07) will increase coverage by 0.68%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #944      +/-   ##
==========================================
+ Coverage   81.15%   81.83%   +0.68%     
==========================================
  Files         183      183              
  Lines        5878     5879       +1     
  Branches     1451     1451              
==========================================
+ Hits         4770     4811      +41     
+ Misses        692      666      -26     
+ Partials      416      402      -14     
Impacted Files Coverage Δ
src/Sentry/Envelopes/Envelope.cs 94.11% <ø> (ø)
src/Sentry/Envelopes/EnvelopeItem.cs 89.47% <ø> (ø)
src/Sentry/Internal/SdkComposer.cs 65.90% <100.00%> (+28.69%) ⬆️
src/Sentry/SentryOptions.cs 90.90% <100.00%> (ø)
src/Sentry/Protocol/Device.cs 87.05% <0.00%> (+0.58%) ⬆️
src/Sentry/Internal/Http/CachingTransport.cs 79.35% <0.00%> (+0.64%) ⬆️
src/Sentry/SentryClient.cs 79.83% <0.00%> (+0.80%) ⬆️
src/Sentry/Request.cs 71.42% <0.00%> (+1.58%) ⬆️
src/Sentry/Protocol/App.cs 98.07% <0.00%> (+1.92%) ⬆️
src/Sentry/User.cs 84.78% <0.00%> (+2.17%) ⬆️
... and 6 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 cacbd07...c42362b. Read the comment docs.

Copy link
Member

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

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

Code looks good but it's missing some tests to cover the new behavior.

One outstanding point is the fact we need to make ISerializable also public. @Tyrrrz won't be back for 3 weeks to chime in but I believe he wanted to refactor things before we make those public. So either we'll wait or we need to figure this out ourselves

/// Represents a serializable entity.
/// </summary>
internal interface ISerializable
public interface ISerializable
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 this was another reason @Tyrrrz wanted to make things internal.
He had some plans to refactor this so types don't need to implement this in order to be serialized.

Copy link
Author

Choose a reason for hiding this comment

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

That's most likely something that goes beyond of my understanding of the code vision of the library right now. I'm happy to help, but if there was an idea how to do this already, I might not think in the direction @Tyrrrz wanted to bring this, so I think it's better to wait for him.

Copy link
Contributor

Choose a reason for hiding this comment

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

As a temp workaround to avoid exposing ISerializable, let's make:

  • EnvelopeItem.Payload internal (or even private? can we do that?)
  • EnvelopeItem.ctor internal (we won't expose a public constructor for envelope)

It's ugly but I think exposing ISerializable right now will constrain us too much. I don't like exposing Envelope either but there's no way around it if we want to expose ITransport.

@pchinery
Copy link
Author

I have now added a test to verify that custom transports a wrapped with a cache. The opposite (to show that no caching is used) would require either to make some properties public on the BackgroundWorker or would require some reflection to verify this. Do you have a preference for any of the two ways or is it good as it is?

Comment on lines +36 to +45
ITransport transport;

if (_options.Transport is not null)
{
transport = _options.Transport;
}
else
{
transport = CreateHttpTransport();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ITransport transport;
if (_options.Transport is not null)
{
transport = _options.Transport;
}
else
{
transport = CreateHttpTransport();
}
var transport = _options.Transport ?? CreateHttpTransport();

/// Represents a serializable entity.
/// </summary>
internal interface ISerializable
public interface ISerializable
Copy link
Contributor

Choose a reason for hiding this comment

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

As a temp workaround to avoid exposing ISerializable, let's make:

  • EnvelopeItem.Payload internal (or even private? can we do that?)
  • EnvelopeItem.ctor internal (we won't expose a public constructor for envelope)

It's ugly but I think exposing ISerializable right now will constrain us too much. I don't like exposing Envelope either but there's no way around it if we want to expose ITransport.

@Alexandr-Pletnev
Copy link

Alexandr-Pletnev commented May 20, 2021

As discussed in #941, this is a proposal to make the ITransport configurable, which required to make the interface and some other classes along the path public.

The transport will be wrapped with caching, if configured.

It's great feature! Thanks.

Could you help me in one use-case?

I have to develop a use-case: Send the Sentry Events from a private side throught RabbitMq to a public side and then send them to Sentry Server.

What I did:

  1. I developed own ITransport that send an Envelope thought RabbitMq.
  2. I developed the RabbitMq consumer that receive the Envelope. Everything ok.
  3. I need to send the Envelope to the Sentry Server. But i can't realise how i can do it.

I will plesant if you help me.

@Tyrrrz
Copy link
Contributor

Tyrrrz commented May 20, 2021

As discussed in #941, this is a proposal to make the ITransport configurable, which required to make the interface and some other classes along the path public.
The transport will be wrapped with caching, if configured.

It's great feature! Thanks.

Could you help me in one use-case?

I have to develop a use-case: Send the Sentry Events from a private side throught RabbitMq to a public side and then send them to Sentry Server.

What I did:

  1. I developed own ITransport that send an Envelope thought RabbitMq.
  2. I developed the RabbitMq consumer that receive the Envelope. Everything ok.
  3. I need to send the Envelope to the Sentry Server. But i can't realise how i can do it.

I will plesant if you help me.

I don't think there's a straightforward way to achieve that (@bruno-garcia can correct me if I'm wrong).

I think your best bet is to write the envelopes from RabbitMQ to a local directory, and pick them up via caching feature:

/// <summary>
/// Path to the root directory used for storing events locally for resilience.
/// If set to <i>null</i>, caching will not be used.
/// </summary>
public string? CacheDirectoryPath { get; set; }

The files will need to be placed in a specific subdirectory as well. Assuming SentryOptions.CacheDirectoryPath = "path/to/some/directory/", the files would need to be seeded in:

path/to/some/directory/Sentry/{your DSN}/

The file name doesn't matter, but the extension has to be .envelope. You can inspect the implementation here for more info: https://github.com/getsentry/sentry-dotnet/blob/984b21063ca806df0129a89aeec011f95012eca5/src/Sentry/Internal/Http/CachingTransport.cs

Cached envelopes are flushed automatically during SentrySdk.Init(...) but can also be flushed manually through SentrySdk.FlushAsync(...) (I think).

That said, all of this is very hacky and I'm not sure how well this will work. We probably need a proper solution for this, but currently all of the relevant interfaces and implementations are internal.

@Alexandr-Pletnev
Copy link

Alexandr-Pletnev commented May 21, 2021

Thank you for your reply.

I decided to achieve this via reflections like that:

`
//

FieldInfo fiHub = typeof(SentrySdk).GetField("_hub", BindingFlags.NonPublic | BindingFlags.Static);
object hub = fiHub.GetValue(null);

FieldInfo fiClient = hub.GetType().GetField("_ownedClient", BindingFlags.NonPublic | BindingFlags.Instance);
object client = fiClient.GetValue(hub);

var mi = client.GetType().GetMethod("CaptureEnvelope", BindingFlags.NonPublic | BindingFlags.Instance);
object result = mi.Invoke(client, new object[] { envelope });

`

@mattjohnsonpint
Copy link
Contributor

Hi. Sorry this PR is open for so long. I'm taking a look now, and it seems like most of what it does has already been addressed by other PRs for other reasons, as follows:

I think to achieve the stated goals, all that needs to be done is to make ITransport and options.Transport public. That would allow others to create their own transports (extending from HttpTransportBase if desired). Unity didn't need that, because they also needed to create their own implementation of IBackgroundWorker - which is public. But we shouldn't require others to do that just to attach a transport.

I'll close this PR and open a new one with that.

@mattjohnsonpint
Copy link
Contributor

See #1602

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.

6 participants