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

Implementing Retry logic [Reliable Channel] #556

Closed
wants to merge 14 commits into from

Conversation

debugthings
Copy link
Contributor

Added retry logic that is similar to the .NET framework.

  • Removes logic from NetworkTransmissionOutput
  • Uses observers to handle error conditions
  • Added failed transmission retry
  • Added partial transmission retry
  • Aligned response codes to match .NET
  • Uses existing ExponentialBackOffTimesPolicy

NOTE This clobbers the change in #385 referenced here

https://github.com/Microsoft/ApplicationInsights-Java/blob/7a5e572b2ffd3256898c6bd05dc3bec6754e3629/core/src/main/java/com/microsoft/applicationinsights/internal/channel/common/TransmissionNetworkOutput.java#L172

All exceptions are now handled by ErrorHandler in this line.

https://github.com/Microsoft/ApplicationInsights-Java/blob/094383a25b0f98fe6aa2dd6dd58bae10259492e6/core/src/main/java/com/microsoft/applicationinsights/channel/concrete/inprocess/ErrorHandler.java#L39-L42

For significant contributions please make sure you have completed the following items:

  • Design discussion issue #
  • Changes in public surface reviewed
  • CHANGELOG.md updated

Copy link
Contributor

@dhaval24 dhaval24 left a comment

Choose a reason for hiding this comment

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

One general change that is required is Java doc comments are missing all over. We need that especially for new public methods and also some private methods which have important logic.

Try to reduce the scope of public methods exposed if possible. I think some can be done.

I did an initial glance over on this, and we would do a functional review soon.

@@ -65,6 +66,7 @@ shadowJar {
relocate 'org.apache.commons', 'com.microsoft.applicationinsights.core.dependencies.apachecommons'
relocate 'com.google.common', 'com.microsoft.applicationinsights.core.dependencies.googlecommon'
relocate 'javax.annotation', 'com.microsoft.applicationinsights.core.dependencies.javaxannotation'
relocate 'com.google.gson', 'com.microsoft.applicationinsights.core.dependencies.gson'
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you use gson for actual code? Or this is only for test? If it is only test I would say do not relocate. Relocation usually should be done when it is absolutely necessary.

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 added Gson to take care of the parsing of the BackendResponse object that is returned from a partial success. There were no JSON deserializers already included in the solution (at least none that were obvious).

Copy link
Contributor

Choose a reason for hiding this comment

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

@debugthings makes sense. Gson was used but only for test cases. Since this is now used for production code we do need to shade it. May be we might not need to shade it still. Gradle will pull this as transitive dependency when building. Shading (i.e repacking) to microsoft domain is only needed when it interferes our agent (one example is apache http client). We shade it to avoid instrumenting the calls sdk makes using it. Gson is a widely used library across java and I would rather avoid shading to prevent us from falling into the traps of class path hells.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough, I also thought that we include it to avoid having to distribute gson with it for instances where this is a drop in addition like a 3rd party.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that was one reason but, this creates problems of dependency hells if we miss proper shading, and more over if the user uses dependency management, which most do then transient dependencies get pulled down. Further as the SDK grows and we start using more libraries, it would make sense to just shade the one which interfer the operation and leave the rest


public class BackendResponse {

public int itemsReceived;
Copy link
Contributor

Choose a reason for hiding this comment

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

Adjust the additional space

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

validateTransmissionAndSend(args);
}

public boolean validateTransmissionAndSend(TransmissionHandlerArgs args) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this method need to be public? If it is not accessed from outside, reduce the scope to private or default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The answer is no, I did this to get my tests working in. I attempted to use Mockito for this, but in version 1.10 they do not support private methods or final classes. This makes it hard to mock a number of items.

Since we have the need to document all public methods I can modify the tests to use Reflection to grab the private member.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah so mockito version 1.10 does not allow mocking private methods. Is this method a part of interface? That's why I was suggesting since this is used widely we can plug it into the interface and then mock it. If that route is not valid for some reason then we might better use reflection. Reducing the publicly exposed methods will improve our abilities to modify it without affecting anyone. Users can take dependency on public methods and modification of signature can thus be very cumbersome.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed this by using the package scope. Only classes defined in the packages can see the method.

Gson gson = gsonBuilder.create();
backend = gson.fromJson(response, BackendResponse.class);
} catch (Throwable t) {
InternalLogger.INSTANCE.trace("Error deserializing backend response with Gson, message: %s",
Copy link
Contributor

Choose a reason for hiding this comment

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

Please print the stack trace also. ExceptionUtils can be used for this.


// In case the 206 was false we can break here
if(beR != null && (beR.itemsAccepted == beR.itemsReceived))
{
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there should be a log message here, with lowest severity.

case HttpStatus.SC_REQUEST_TIMEOUT:
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
case HttpStatus.SC_SERVICE_UNAVAILABLE:
case 429:
Copy link
Contributor

Choose a reason for hiding this comment

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

So we don't handle 429 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eh? In the partial success handler any an all error messages are treated the same. In this instance the partial success will try to resend any of these items in the next transmission.

https://github.com/Microsoft/ApplicationInsights-dotnet/blob/0fe5edf099ecdad37990be0c776b300e7fbcff4a/src/ServerTelemetryChannel/Implementation/PartialSuccessTransmissionPolicy.cs#L107-L111

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah got it. So this means if partial message was accepted, then we would retry the whole packet correct?

}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't print stack trace. Instead dump it using Internal Logger


}

private static Date convertToDateToGmt(Date date) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We need java docs for all the methods and their description. It is crucial for all public methods and private methodsl like this where there is core logic.

validateTransmissionAndSend(args);
}

public boolean validateTransmissionAndSend(TransmissionHandlerArgs args) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to previous does this method need to be public. More-ever can we create an abstraction for this too, like an interface because it seems like this is being used in different handler classes you created.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed this by using the package scope. Only classes defined in the packages can see the method.

return true;

} catch (ConnectionPoolTimeoutException e) {
ex = e;
Copy link
Contributor

Choose a reason for hiding this comment

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

All this places we need to dump the stack trace. Please use ExceptionUtils to do so and pass it in logger.

@dhaval24 dhaval24 changed the title Implementing Retry logic Implementing Retry logic [Reliable Channel] Feb 12, 2018
public void setResponseCode(int code) { this.responseCode = code;}
public int getResponseCode() { return this.responseCode;}

private Throwable exception;
Copy link
Contributor

Choose a reason for hiding this comment

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

@debugthings do we ever get a Throwable here? I think most of the time it would get an instance of Exception class. If you know any place where this could be Throwable please let me know

Copy link
Contributor Author

@@ -46,8 +50,16 @@
*
* Created by gupele on 6/29/2015.
*/
public final class TransmissionPolicyManager implements Stoppable {

public final class TransmissionPolicyManager implements Stoppable, TransmissionHandlerObserver {
Copy link
Contributor

Choose a reason for hiding this comment

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

So we had to change the public class also, I think which is fine. However, if some of our users if they had taken dependency on this. we would break them by this change. I am not sure we might need to consider a separate release for this, mentioning that there can be some breaking changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe. We added four public methods to this but did not remove any; and didn't change the implementation of existing methods. That shouldn't break the contract and the code should execute as expected. Might well warrant a deeper discussion

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm

* @return A List<> of each sent item
*/
List<String> generateOriginalItems(TransmissionHandlerArgs args) {
List<String> originalItems = new ArrayList<String>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Types in <> in Java 7 and onwards can be auto-inferred and is more efficient. This can be replaced with
List originalItems = new ArrayList<>();

List<String> originalItems = generateOriginalItems(args);

// Somehow the amount of items received and the items sent do not match
if (beR != null && (originalItems.size() != beR.itemsReceived)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to make this condition more robust. This could be more apt
if (beR != null && (originalItems.size() < beR.itemsReceived))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure I agree, if these numbers don't match then there was a problem with the transmission and we're in an invalid state I would think. Either the original content was broken or the response is broken

return false;
}

if (beR != null && (beR.itemsAccepted != beR.itemsReceived)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly for this the condition can be changed to
if (beR != null && (beR.itemsAccepted < beR.itemsReceived)
This makes it logically more clear and better readable code. IMO the condition in itself is also more robust.

if (beR != null && (beR.itemsAccepted != beR.itemsReceived)) {

List<String> newTransmission = new ArrayList<String>();
for (BackendResponse.Error e : beR.errors) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we replace this for-each loop with a for loop like this :
for (int i = 0; i < ber.errors.length; ++i). This would help simplify the index operation being used mutiple times. We can the just do
if (i < originalItems.size()) {
newTransmission.add(originalItems.get(i));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The index of the items in the errors array is not guaranteed to be the index of the original item sent.

errors[0] = Error() { index = 2, responseCode = 500, message = "Internal Error" }

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah this is a catch. Got it

boolean validateTransmissionAndSend(TransmissionHandlerArgs args) {
if (args.getRetryHeader() != null && args.getTransmission() != null
&& args.getTransmissionDispatcher() != null) {
args.getTransmission().incrementNumberOfSends();
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that PartialResponseHandler class doesn't increment the number of sends like this. Is there a reason why it is omitted there? Because eventually we are retrying correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this instance we're creating a brand new transmission to send based on the result of the old one. We are not going to dispatch the entire transmission so no need to increment.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

Date date = formatter.parse(retryAfterAsString);

Date now = Calendar.getInstance().getTime();
long retryAfterAsSeconds = (date.getTime() - convertToDateToGmt(now).getTime()) / 1000;
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like this calculation is always fixed. I might have missed something , please point out to where we are doing exponential backoff in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For Throttling requests the server provides the backoff time in the form of the Retry-After header. If that header is missing or invalid (will throw) I call backoff in the catch block

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense. I would say to mention a comment!

@@ -68,6 +68,15 @@ public SenderThreadLocalBackOffData(long[] backOffTimeoutsInMillis, long addMill
public boolean isTryingToSend() {
return currentBackOffIndex != -1;
}

Copy link
Contributor

@dhaval24 dhaval24 Feb 12, 2018

Choose a reason for hiding this comment

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

Missing Java docs for getCurrentBackOffMillis()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not needed, removed

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay

}
}

public long backOffTimerValue() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Java docs missing for this method

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -75,6 +80,11 @@ public synchronized void stopAllSendersBackOffActivities() {
}
stopped = true;
}

public long getCurrentBackoffMillis() {
Copy link
Contributor

Choose a reason for hiding this comment

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

docs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

@@ -24,8 +24,9 @@
/**
* Created by gupele on 6/29/2015.
*/
enum TransmissionPolicy {
public enum TransmissionPolicy {
Copy link
Contributor

Choose a reason for hiding this comment

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

Update java docs for this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed public.

import java.util.concurrent.TimeUnit;

/**
* The class is responsible for the actual sending of {@link com.microsoft.applicationinsights.internal.channel.common.Transmission}
* The class is responsible for the actual sending of
* {@link com.microsoft.applicationinsights.internal.channel.common.Transmission}
*
* The class uses Apache's HttpClient framework for that.
*
* Created by gupele on 12/18/2014.
*/
public final class TransmissionNetworkOutput implements TransmissionOutput {
Copy link
Contributor

Choose a reason for hiding this comment

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

There are bunch of methods in this class which do not have java docs. It would be good if we can update those places as we are changing this part.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added docs for public and private methods.


public final class TransmissionPolicyManager implements Stoppable, TransmissionHandlerObserver {

private final int DEFAULT_MAX_SECONDS_TO_PAUSE_AFTER_MAX_BACKOFF = 600;
Copy link
Contributor

@dhaval24 dhaval24 Feb 12, 2018

Choose a reason for hiding this comment

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

How did we came up with this number ? 600 Seconds seems to be too long. In a situation where the network is very restricted this would accumulate bulk of telemetry. Also is this configurable by channel in xml? If not it should be

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, 10 minutes is a long time and it should be configurable. In the .NET implementation it will max out at 30 minutes in the backoff algorithm. Let's talk about this a bit more to see what we really want to do. By the time we reach this point we would have executed the backoff 15 times and probably have been throttled well over 15 minutes. It's possible this is just redundant.

Copy link
Contributor

Choose a reason for hiding this comment

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

@debugthings Yes, ideally I would want that to be configurable too. So instead of keeping that 15 constants for back of we have some sort of iterator pattern implemented which keeps on providing new backoff numbers until user specified limit. Internally iterator could well be implemented as Geometric Progression with ratio of 2. If we want to interleave with a constant time that could also be done.

if (args.getTransmission() != null && args.getTransmissionDispatcher() != null) {
switch (args.getResponseCode()) {
case HttpStatus.SC_PARTIAL_CONTENT:
BackendResponse beR = getBackendResponse(args.getResponseBody());
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit picking: Please use a more descriptive name instead of beR. "backendResponse" would be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, fixed.



List<String> newTransmission = new ArrayList<String>();
for (BackendResponse.Error e : beR.errors) {
Copy link
Contributor

Choose a reason for hiding this comment

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

null check missing for beR. I'd suggest checking for null right after line 39.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed with logic update

@@ -24,7 +24,7 @@
/**
* Created by gupele on 2/10/2015.
*/
enum TransmissionSendResult {
public enum TransmissionSendResult {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to make this enum public? Is it required for test cases? If yes please follow the Java Doc requirements and update the comment to be java doc comment with description.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nah, must have been done via some Intellisense suggestion. Removed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Haha, got it!

Copy link
Contributor

@dhaval24 dhaval24 left a comment

Choose a reason for hiding this comment

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

I have done second round of review and left my comments. I would like to have those changes. Further, I am mandating the need of java docs and being a little bit stricter on this because we are following this requirement for all new check-ins and is also mandatory for quality API

Moved the Handlers out of the concrete package to the common package to keep the same consistency.  Removed a couple of unessecary methods. Added docs.
} catch (ConnectionPoolTimeoutException e) {
ex = e;
InternalLogger.INSTANCE.error(
"Failed to send, connection pool timeout exception\r\n" + "Stack Trace:\r\n" + "%s",
Copy link
Contributor

Choose a reason for hiding this comment

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

Use %n and the format string chooses the correct EOL characters. Same with the rest of the log messages.
Also, let's remove the unnecessary concatenations; I don't know if JIT is smart enough to optimize this into one string literal. Let's assume it's not and merge these into one string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good, eclipse auto format causes this most likely because I'm not using the %n string.

Copy link
Contributor

Choose a reason for hiding this comment

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

I looked it up and JIT is smart enough to turn those into one literal, so I'm less concerned with the concatenation. :)

@@ -135,11 +135,13 @@ public TransmissionFileSystemOutput(String folderPath) {
@Override
public boolean send(Transmission transmission) {
if (size.get() >= capacityInKB) {
InternalLogger.INSTANCE.logAlways(InternalLogger.LoggingLevel.TRACE, "Persistent storage max capcity has been reached; currently at %s KB. Telemetry will be lost, please set the MaxTransmissionStorageFilesCapacityInMB property in the configuration file.", size.get());
Copy link
Contributor

@littleaj littleaj Feb 12, 2018

Choose a reason for hiding this comment

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

I think this is a WARN level log. It's an exceptional case, but everything is still operational.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think things are operational, however when this would happen it would indicate loss of telemetry. Imagine a banking application where this occurs and they loss transactional logs which were eventually needed for fraud analysis then this could be critical information. I would keep it as logalways and since this is rare I don't think it would any how effect production loads.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm suggesting changing it to InternalLogger.INSTANCE.logAlways(InternalLogger.LoggingLevel.WARN, ... I also think it should be logAlways.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, WARN makes more sense as it's something that is actionable but not ex

return false;
}

Optional<File> tempTransmissionFile = createTemporaryFile();
if (!tempTransmissionFile.isPresent()) {
InternalLogger.INSTANCE.logAlways(InternalLogger.LoggingLevel.TRACE, "Persistent storage unable to create temporary file.");
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is an ERROR level log. We can still run (i.e. it's not FATAL), but this component cannot do what it's designed to do.

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 am removing this as it's redundant. There is a logger call in createTemporaryFile()

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.

case HttpStatus.SC_REQUEST_TIMEOUT:
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
case HttpStatus.SC_SERVICE_UNAVAILABLE:
case 429:
Copy link
Contributor

Choose a reason for hiding this comment

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

For the 429 and 439 case, can you append those lines with comments with a "friendly name" (similar to the constants in the previous cases)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed with constants mentioned in other change.

case HttpStatus.SC_REQUEST_TIMEOUT:
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
case HttpStatus.SC_SERVICE_UNAVAILABLE:
case 429:
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 create constants for 429 and 439?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think probably we should. It would allow when we extend the support later to support this codes.

Copy link
Contributor

Choose a reason for hiding this comment

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

HttpStatus is part of the Apache HttpClient. Will a comment be sufficient?

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 it makes more sense to have this as a constant. I modified TransmissionSendResult as it wasn't used anywhere else and was internal to the com.microsoft.applicationinsights.internal.channel.common package

return instanceIsActive;
} catch (InterruptedException e) {
return false;
if (!instanceIsActive) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@debugthings is it true that thread will never starve in the same state (i.e blocked state). If not we might always hit this condition for certain thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, this is an artifact of the blocking backoff implementation (which I left intact). The only way for this to get set is if someone calls stop(). It's highly unlikely that it will be called since it's not referenced anywhere in the code.

It's in place to make sure if someone wants to disable the backoff they can do so with stop. Not surprisingly there is no start method so once the manager is stopped that's it

Copy link
Contributor

Choose a reason for hiding this comment

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

If there is a feature like this to disable the backoff it should be documented. And if there is no way to start if back then stop also doesn't make sense to me. Either case I think if we want to keep it just comment on it , regarding it is not advised to use this at any point or just remove the method if we do not plan to have this functionality.

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 am all for deleting code that is not used.

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 left this code intact as there are some old tests that are dependent on it and that is too much to tackle in this PR. Created task #559 to follow up

private TransmissionNetworkOutput(String serverUri, TransmissionPolicyManager transmissionPolicyManager) {
Preconditions.checkNotNull(serverUri, "serverUri should be a valid non-null value");
Preconditions.checkArgument(!Strings.isNullOrEmpty(serverUri), "serverUri should be a valid non-null value");
Preconditions.checkNotNull(transmissionPolicyManager,
Copy link
Contributor

Choose a reason for hiding this comment

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

What are scenarios where this could be null. How does code flow happen in case of this event?

Copy link
Contributor

Choose a reason for hiding this comment

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

The Preconditions statements are for us. Callers of this method should make sure serverUri is not null before calling.

Copy link
Contributor

@dhaval24 dhaval24 left a comment

Choose a reason for hiding this comment

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

Looks good to me

Copy link

@AlexKlimovMS AlexKlimovMS left a comment

Choose a reason for hiding this comment

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

Two minor comments

InternalLogger.INSTANCE.logAlways(InternalLogger.LoggingLevel.TRACE, "App is throttled, telemetry will be blocked for %s seconds.", backOffSeconds);
this.suspendInSeconds(TransmissionPolicy.BACKOFF, backOffSeconds);
} else {
// TODO Remove Static Time

Choose a reason for hiding this comment

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

Is this TODO still needed?


public void clearBackoff() {
policyState.setCurrentState(TransmissionPolicy.UNBLOCKED);
backoffManager.onDoneSending();

Choose a reason for hiding this comment

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

Minor: extra spaces.

@grlima
Copy link
Contributor

grlima commented Feb 27, 2018

Replaced by #561

@grlima grlima closed this Feb 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants