I was able to successfully integrate the elastic search sink in my .net app, now I am trying to setup the FailureCallback option but every time there is an error the exception in LogEvent is null, I can see the actual error in the console but I want to be able to capture this exception in my failure callback function, here is my current configuration:
myLogger = new LoggerConfiguration()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elasticSearchUrl))
{
AutoRegisterTemplate = true,
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6,
IndexDecider = (#event, dateTimeOffset) =>
{
//some logic here
return $"custom-index";
},
EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog | EmitEventFailureHandling.RaiseCallback,
FailureCallback = HandleElasticError
})
.Enrich.WithProperty("Environment", Config.Environment)
.Destructure.ByTransforming<ExpandoObject>(JsonConvert.SerializeObject)
.CreateLogger();
Here is my HandleElasticError function:
private void HandleElasticError(LogEvent e)
{
FileLogger.Error(e.Exception, e.MessageTemplate.Text, e.Properties);
}
When I attach the debugger and inspect the LogEvent, exception is null, however in the output window in Visual Studio I can see the actual error:
2020-11-30T20:55:07.7820674Z Caught exception while preforming bulk operation to Elasticsearch: Elasticsearch.Net.ElasticsearchClientException: The underlying connection was closed: An unexpected error occurred on a send.. Call: Status code unknown from: POST /_bulk ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: The handshake failed due to an unexpected packet format.
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
I am not concerned about the error, I know what the issue is, I just want to be able to capture this exception in my failure callback function.
Any ideas?
LogEvent.Exception is the Exception shipped with your call to (for example) logger.Error(myException) - not the exception thrown by failure to write to Elastic Search.
The exception you're trying to catch doesn't look to be exposed by the sink as it just passes the LogEvent to FailureCallback and not exception that caused the failure.
Here's what it could look like were the exception exposed.
you can use:
StreamWriter writer = File.CreateText(...);
Serilog.Debugging.SelfLog.Enable(writer);
Related
I am testing an Xamarin.iOS Application on a real device (iPhone 6s with iOS 12.1) with Xamarin.UITest.
When I am running my few UI Tests, the first test always seam to crash (regardless of what is happening inside the test) due to the same error (see below).
Enviroment is:
Xamarin.UITest 2.2.7
NUnitTestAdapter 2.1.1
NUnit 2.6.3
Xamarin.TestCloud.Agent 0.21.7
Setup is:
[SetUp]
public void Setup(){
this.app = ConfigureApp.iOS
.EnableLocalScreenshots()
.InstalledApp("my.app.bundle")
.DeviceIdentifier("My-iPhone6s-UDID-With-iOS12.1")
.StartApp();
}
[Test]
public void FirstTestThatCouldBeEmpty(){
//But doesn't have to be empty to produce the error
}
Resulting error:
2019-01-17T14:11:20.4902700Z 1 - ClearData:> 2019-01-17T14:11:20.4916340Z bundleId: my.app.bundle
2019-01-17T14:11:20.4929580Z deviceId: My-iPhone6s-UDID-With-iOS12.1
2019-01-17T14:11:33.7561260Z 3 - LaunchTestAsync:
2019-01-17T14:11:33.7574050Z deviceId: My-iPhone6s-UDID-With-iOS12.1
2019-01-17T14:11:33.9279420Z 5 - HTTP request failed, retry limit hit
2019-01-17T14:11:33.9302300Z Exception: System.Net.Http.HttpRequestException: An error occurred while sending the request ---> System.Net.WebException: Unable to read data from the transport connection: Connection reset by peer. ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer
2019-01-17T14:11:33.9322710Z at System.Net.Sockets.Socket.EndReceive (System.IAsyncResult asyncResult) [0x00012] in <23340a11bb41423aa895298bf881ed68>:0
2019-01-17T14:11:33.9340560Z at System.Net.Sockets.NetworkStream.EndRead (System.IAsyncResult asyncResult) [0x00057] in <23340a11bb41423aa895298bf881ed68>:0
2019-01-17T14:11:33.9358740Z --- End of inner exception stack trace ---
2019-01-17T14:11:33.9377100Z at System.Net.Sockets.NetworkStream.EndRead (System.IAsyncResult asyncResult) [0x0009b] in <23340a11bb41423aa895298bf881ed68>:0
2019-01-17T14:11:33.9398100Z at System.IO.Stream+<>c.b__43_1 (System.IO.Stream stream, System.IAsyncResult asyncResult) [0x00000] in <98fac219bd4e453693d76fda7bd96ab0>:0
2019-01-17T14:11:33.9415720Z at System.Threading.Tasks.TaskFactory1+FromAsyncTrimPromise1[TResult,TInstance].Complete (TInstance thisRef, System.Func`3[T1,T2,TResult] endMethod, System.IAsyncResult asyncResult, System.Boolean requiresSynchronization) [0x00000] in <98fac219bd4e453693d76fda7bd96ab0>:0
Sometimes it is this error:
SetUp : Xamarin.UITest.XDB.Exceptions.DeviceAgentException : Unable to end session: An error occurred while sending the request
System.Net.Http.HttpRequestException : An error occurred while sending the request
System.Net.WebException : Unable to read data from the transport connection: Connection reset by peer.
System.IO.IOException : Unable to read data from the transport connection: Connection reset by peer.
System.Net.Sockets.SocketException : Connection reset by peer
What could be a solution to this?
Doing the version puzzle of the nuget packages got me this far, that all tests are working besides this one.
A dummy test would be a possibility, but that would that countinous builds with those test would never be in the state of "successful" because this one test that is failing =(
I was able to find a work around for this issue, and really any issue with the device agent not connecting to the app under test.
public static IApp StartApp(Platform platform)
{
if (platform == Platform.iOS)
{
try
{
return ConfigureApp.iOS
.InstalledApp("com.example")
#if DEBUG
.Debug()
#endif
.StartApp();
}
catch
{
return ConfigureApp.iOS
.InstalledApp("com.example")
#if DEBUG
.Debug()
#endif
.ConnectToApp();
}
}
In plain language : "If you tried to start the app, and something went wrong, try to see if the app under test was started anyway and connect to it"
Note : As https://stackoverflow.com/users/1214857/iupchris10 mentioned in the comments, a caveat to this approach is that when you run tests consecutively, while the StartApp call will in theory reliably shut down the app, with the point of failure being reconnection, if it does not and you are running tests consecutively, you will simply connect to the running app instance in whatever state it was left in. This approach offers no recourse. Xamarin's StartApp will throw Exception, rather than a typed exception, and so mitigating this will rely on you parsing InnerException.Message and keeping a table of expected failures.
I am working on application in Xamarin forms for Android and iOS. App is getting data from Rest Api and It was working fine till yesterday but today some SSL issues was fixed from the server admin. Now Rest Api is working fine from Chrome browser and we are getting data. Even it is working on Visual Studio for Mac and working fine on simulator.
But on Android it is not working. I have checked the domain with https://www.digicert.com/help/ and it gives the OK result as "Congratulations! This certificate is correctly installed.".
I am using the below code:
var response = client.GetAsync(urlCategories).Result;
string content = "";
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
content = responseContent.ReadAsStringAsync().Result;
}
Below is the complete stack trace of the error:
{Javax.Net.Ssl.SSLHandshakeException:
Chain validation failed ---> Java.Security.Cert.CertificateException:
Chain validation failed ---> Java.Security.Cert.CertPathValidatorException:
OCSP response does not include a response for a certificate supplied in the OCSP request ---> Java.Security.Cert.CertPathValidatorException:
OCSP response does not include a response for a certificate supplied in the OCSP request
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in <42dc777b518744fdae9988e94489a4a0>:0
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00014] in <42dc777b518744fdae9988e94489a4a0>:0
at Javax.Net.Ssl.HttpsURLConnectionInvoker.Connect () [0x0000a] in <1219ce5aae934ab095dc0e05b2110050>:0
at Xamarin.Android.Net.AndroidClientHandler+<>c__DisplayClass43_0.<ConnectAsync>b__0 () [0x0005a] in <1219ce5aae934ab095dc0e05b2110050>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x0000f] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Execute () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
--- End of stack trace from previous location where exception was thrown ---
at Xamarin.Android.Net.AndroidClientHandler+<DoProcessRequest>d__45.MoveNext () [0x0012e] in <1219ce5aae934ab095dc0e05b2110050>:0
--- End of stack trace from previous location where exception was thrown ---
at Xamarin.Android.Net.AndroidClientHandler+<SendAsync>d__40.MoveNext () [0x00230] in <1219ce5aae934ab095dc0e05b2110050>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.HttpClient+<SendAsyncWorker>d__49.MoveNext () [0x000ca] in <25ebe1083eaf4329b5adfdd5bbb7aa57>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.HttpClient+<GetStringAsync>d__54.MoveNext () [0x0007d] in <25ebe1083eaf4329b5adfdd5bbb7aa57>:0
--- End of stack trace from previous location where exception was thrown ---
at Guldasta.Gen+<GetMenuItems>d__86.MoveNext () [0x00045] in E:\05_Xamarin_Projects\GuldastaApp\Guldasta\Guldasta\Guldasta\General\Gen.cs:62
--- End of managed Javax.Net.Ssl.SSLHandshakeException stack trace ---
javax.net.ssl.SSLHandshakeException: Chain validation failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:1477)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1423)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1367)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:219)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:142)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:104)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:392)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:325)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:489)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(Unknown Source:0)
Caused by: java.security.cert.CertificateException: Chain validation failed
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:788)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:612)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:633)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:678)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:499)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:422)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:343)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:607)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 12 more
Caused by: java.security.cert.CertPathValidatorException: OCSP response does not include a response for a certificate supplied in the OCSP request
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:143)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
at com.android.org.conscrypt.DelegatingCertPathValidator.engineValidate(DelegatingCertPathValidator.java:44)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:784)
... 24 more
Caused by: java.security.cert.CertPathValidatorException: OCSP response does not include a response for a certificate supplied in the OCSP request
at sun.security.provider.certpath.OCSPResponse.verify(OCSPResponse.java:416)
at sun.security.provider.certpath.RevocationChecker.checkOCSP(RevocationChecker.java:709)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:363)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:337)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
... 30 more
Suppressed: java.security.cert.CertPathValidatorException: Could not determine revocation status
at sun.security.provider.certpath.RevocationChecker.buildToNewKey(RevocationChecker.java:1092)
at sun.security.provider.certpath.RevocationChecker.verifyWithSeparateSigningKey(RevocationChecker.java:910)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:577)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:465)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:394)
... 32 more
Do anyone have the idea how can solve this issue?
This works for Android:
//Code for disabling SSL certificate
internal class BypassHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
public bool Verify(string hostname, ISSLSession session)
{
return true;
}
}
internal class BypassSslValidationClientHandler : Xamarin.Android.Net.AndroidClientHandler
{
protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
{
return Android.Net.SSLCertificateSocketFactory.GetInsecure(1000, null);
}
protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
{
return new BypassHostnameVerifier();
}
}
var handler = new BypassSslValidationClientHandler();
using (HttpClient client = new HttpClient(handler))
using this handler in HTTP request
Note: this is the temporary workaround you should fix this issue on the server side. (API side)
I am attempting to retrieve the HttpStatusCode from every UploadAsync method call. I need the status code as to properly perform an exponential back-off algorithm to retry a failed upload, display an error message to the user when not retrying the upload and to report success of the upload. I do not care how it is received, so long as it is clean and not being parsed from the Exception.Message (string) property like Tor Jonsson suggested in the link provided below.
To force the "Bad Request Error [400]" I simply provided an invalid userkey (email) in the constructor for MailResource.InsertMediaUpload.
e.g. MailResource.InsertMediaUpload(mailItem, "invalidEmail#domain.com", stream, "message/rfc822")
Problem
1) GoogleApiException.HttpStatusCode is always 0 (unavailable). Even when Exception.Message appears to contain a status code in brackets. e.g. [400]
2) Cannot find GoogleApiRequestException.
Questions
1) What is the best way to perform the exponential back-off algorithm???
2) Is this the expected behaviour for this property in this case?
3) Does GoogleApiRequestException still exist, if so where?
Side Note:
I also noticed that the GoogleApiRequestException class is no longer in the same file as GoogleApiException class. Has it been moved to another namespace or deleted? Because I would like to attempt to catch a GoogleApiRequestException object and grab its RequestError object.
I added links to the two diffs for what I mean:
Before: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=a8e27790f8769c1d6aaae030bb46c79daa7cdbad
After: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=d6f06e92d90b635c179013e2c287b42b82909c09
Sources
I'm using the latest binaries from NuGet (1.6.0.8-beta)
The only question I found related to my problem: (Can only post two links... heres the raw)
stackoverflow.com/questions/18985306/httpstatuscode-not-set-in-exceptions-when-using-google-net-apis
Code: (Using a custom logger to write to debugview)
public int Index; // Used to Id the process
private void TryUpload(MailResource.InsertMediaUpload upload, out IUploadProgress uploadProgress, out bool retryUpload)
{
uploadProgress = null;
retryUpload = false;
CancellationToken token;
try
{
uploadProgress = upload.UploadAsync(token).Result;
if (uploadProgress.Exception != null)
{
_logger.WriteTrace("EXCEPTION!!! Type: {0}", uploadProgress.Exception.GetType().ToString()); // Remove:
// *) Handle all of the various exceptions
if (uploadProgress.Exception is JsonReaderException)
{
JsonReaderException jreEx = uploadProgress.Exception as JsonReaderException;
_logger.WriteTrace("JsonReaderException-> Message: {0}", jreEx.Message);
}
if (uploadProgress.Exception is TokenResponseException)
{
TokenErrorResponse trEx = uploadProgress as TokenErrorResponse;
_logger.WriteTrace("TokenErrorResponse-> Message: {0}", trEx.Error);
}
if (uploadProgress.Exception is HttpRequestValidationException)
{
HttpRequestValidationException hrvEx = uploadProgress.Exception as HttpRequestValidationException;
_logger.WriteTrace("HttpRequestValidationException-> Message: {0}", hrvEx.Message);
_logger.WriteTrace("HttpRequestValidationException-> Status Code: {0}", hrvEx.GetHttpCode());
}
if (uploadProgress.Exception is GoogleApiException)
{
GoogleApiException gApiEx = uploadProgress.Exception as GoogleApiException;
_logger.WriteTrace("GoogleApiException-> Message: {0}", gApiEx.Message);
_logger.WriteTrace("GoogleApiException-> Status Code: {0}", gApiEx.HttpStatusCode);
}
}
}
catch (Exception ex)
{
_logger.WriteTrace(ex, "An exception occured while uploading...");
}
finally
{
if (uploadProgress != null)
_logger.WriteTrace("Upload Completed... Status: {0} Exception?: {1}",
uploadProgress.Status,
(uploadProgress.Exception == null) ? "None" : uploadProgress.Exception.ToString());
else
_logger.WriteTrace("Upload Aborted... Exited without returning a status!");
}
}
Output Snippet
[5224] (T101) VSLLC: EXCEPTION!!! Type: Google.GoogleApiException
[5224] (T101) VSLLC: GoogleApiException-> Message: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224] (T101) VSLLC: GoogleApiException-> Status Code: 0
[5224] (T101) VSLLC: Upload Completed... Status: Failed Exception?: The service admin has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224]
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
[5224] at Google.Apis.Upload.ResumableUpload`1.d__0.MoveNext() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis\Apis[Media]\Upload\ResumableUpload.cs:line 373
Sorry for the extensive post! Thanks for your time!
The library already supports exponential back-off for 503 responses. In case of 400 (bad request) you should not retry, because you will get the same response over and over again.
Take a look in the service initializer parameter DefaultExponentialBackOffPolicy
You can also take a look in our ExponentialBackOff implementation. BackOffHandler wraps the logic and implements unsuccessful response handler and exception handler.
GoogleApiRequest doesn't exists anymore.
It looks like we are not setting the status code properly, as you can find here. I open a new issue in our issue tracker, available here - https://code.google.com/p/google-api-dotnet-client/issues/detail?id=425. Feel free to add more content to it.
UPDATED w/ additional CODE
Using Netty 4.0.12, we're getting an IllegalStateException from HttpObjectEncoder if we try to send a message immediately after our websocket is connected (see exception at the bottom). If I sleep a 1 - 2 secs, then everything is fine.
I thought this was because we weren't handling the ChannelFuture properly, but I believe I've fixed that by waiting for the future to be completed using the following logic on the ChannelFuture to ensure the connect is completed before we attempt to use it.
Unfortunately, that didn't fix it. If anyone knows what might be causing this, please let me know.
Thanks in advance,
Bob
=====================
WEBSOCKET CREATION
public synchronized Channel createWebSocket(String id, NettyClientConnection connection) throws Exception
{
URI serverUri = connection.getServerUri();
final ClientHandler clientHandler = new ClientHandler(connection);
this.getBootstrap().handler(new ChannelPipelineInitializer(serverUri, clientHandler));
ChannelFuture future = this.getBootstrap().connect(serverUri.getHost(), serverUri.getPort());
// verify connect has completed successfully
NettyUtils.waitForChannelCompletion(future, "connecting websocket");
Channel websocket = future.channel();
return websocket;
}
PIPELINE INIT
public class ChannelPipelineInitializer extends ChannelInitializer<SocketChannel>
{
private URI _serverUri = null;
protected URI getServerUri(){return this._serverUri;}
private ClientHandler _clientHandler = null;
protected ClientHandler getClientHandler(){return this._clientHandler;}
public ChannelPipelineInitializer(URI serverUri, ClientHandler clientHandler)
{
this._serverUri = serverUri;
this._clientHandler = clientHandler;
}
#Override
public void initChannel(SocketChannel channel) throws Exception
{
ChannelPipeline pipeline = channel.pipeline();
boolean handleCloseFrames = false;
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(this.getServerUri(), WebSocketVersion.V13, null, false, null);
final WebSocketClientProtocolHandler websocketHandler = new WebSocketClientProtocolHandler(handshaker, handleCloseFrames);
DefaultEventExecutorGroup nettyExecutor = new DefaultEventExecutorGroup(10);
pipeline.addLast(PipelineConstants.HttpClientCodec, new HttpClientCodec());
pipeline.addLast(PipelineConstants.HttpAggregator, new HttpObjectAggregator(65536));
pipeline.addLast(PipelineConstants.WebSocketClientProtocolHandler, websocketHandler);
pipeline.addLast(PipelineConstants.ThingworxMessageCodec, new ThingworxMessageCodec());
// use netty executor to free up initial IO thread
pipeline.addLast(nettyExecutor, this.getClientHandler());
}
}
CHANNEL WAIT LOGIC
public static void waitForChannelCompletion(ChannelFuture future, String operationMessage) throws IOCompletionException
{
future.awaitUninterruptibly();
// Now we are sure the future is completed.
if (future.isDone())
{
if (future.isCancelled())
{
String errorMsg = String.format("IO Operation has been cancelled [operation: %s]", operationMessage);
throw new IOCompletionException(errorMsg);
}
else if (future.isSuccess() == false)
{
String errorMsg = String.format("IO Operation failed [operation: %s]", operationMessage);
throw new IOCompletionException(errorMsg, future.cause());
}
}
else
{
// future should be done, otherwise there's a problem
String errorMsg = String.format("IO Operation never completed [operation: %s]", operationMessage);
throw new IOCompletionException(errorMsg);
}
}
EXCEPTION STACK
2013-11-21 13:32:16.767-0500 [ERROR] [c.t.t.t.SendTask] [T: pool-2-thread-9] Client_9 Attempt to send message failed. java.lang.IllegalStateException: unexpected message type: UnpooledUnsafeDirectByteBuf
at io.netty.handler.codec.http.HttpObjectEncoder.encode(HttpObjectEncoder.java:80) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.handler.codec.http.HttpClientCodec$Encoder.encode(HttpClientCodec.java:94) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:89) ~[netty-all-4.0.12.Final.jar:na] Wrapped by: io.netty.handler.codec.EncoderException: java.lang.IllegalStateException: unexpected message type: UnpooledUnsafeDirectByteBuf
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.CombinedChannelDuplexHandler.write(CombinedChannelDuplexHandler.java:193) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:645) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:699) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:638) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:115) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:645) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:699) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:638) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:115) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.handler.codec.MessageToMessageCodec.write(MessageToMessageCodec.java:116) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:645) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.access$2000(DefaultChannelHandlerContext.java:29) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext$WriteTask.run(DefaultChannelHandlerContext.java:906) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353) ~[netty-all-4.0.12.Final.jar:na]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) ~[netty-all-4.0.12.Final.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_45]
It looks like what's happening is this
1) Client sends upgrade request
2) Server sends upgrade response to client, fires local HANDSHAKE_COMPLETED event
3) Upstream server handlers hear event, start sending websocket frames to client
4) Client receives upgrade response (HTTP 101)
5) Client receives first websocket frame before #4 reaches websocket handshaker
HttpClientCodec throws exception here while processing websocket frame, causing websocket handshaker to close connection
6) Client processes upgrade response and removes HttpClientCodec (oops, too late)
I'm also seeing this with 4.0.14.Final, but with HttpClientCodec at the front of the pipeline.
** UPDATE **
This is fixed, btw: https://github.com/netty/netty/issues/2173
I want to log all error message for failed HTTP request. I am going to run the thread group for 1B users and I don't want to use the View Result Tree because it logs everything and log file will bloat.
Currently I am using Beanshell Assertion as below.
if (Boolean.valueOf(vars.get("DEBUG"))) {
if (ResponseCode.equals("200") == false) {
log.info(SampleResult.getResponseMessage());
log.info("There was some problem");
}
}
But in this case it just prints the error message but I am interested to log the stack trace returned by the server.
I also used this method as mention in this thread
for (a: SampleResult.getAssertionResults()) {
if (a.isError() || a.isFailure()) {
log.error(Thread.currentThread().getName()+": "+SampleLabel+": Assertion failed for response: " + new String((byte[]) ResponseData));
}
}
But in this case I don't get an object out of SampleResult.getAssertionResults() method and it doesn't display anything in case of HTTP request failure.
Any idea how to get the stacK trace?
I figured it out. SampleResult has one more method called getResponseDataAsString(). This method returns the response message. In case of error it contains the error message.