I have a Grails application that makes HTTP requests to a back end server for it's data. That server can be taken down for maintenance, and when that happens it will return a "site down" message to the Grails app in the HTTP response. The Grails app is detecting this and throws a custom SiteDownException. In URLMappings.groovy this is then directed to a specific error page.
This works well apart from for AJAX requests. What seems to happen is that the "site down" URL mapping is triggered (as expected) followed by the catch all '500' mapping.
URLMappings.groovy
"500"(controller: "error", action: "siteDown", exception: SiteDownException)
"500"(controller: "error", action: "error500")
ErrorController.groovy
def siteDown() {
println ">>>> site down <<<<"
}
def error500() {
println ">>>> 500 <<<<"
}
The error is thrown using
throw new SiteDownException()
For regular requests the stacktrace shows...
[11/11/13 16:52:50.945 error] SiteDownException occurred when processing request: [POST] /portal/contact/detail - parameters:
fileKeyIdentifier:
mode: add
Stacktrace follows: [org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver http-bio-8080-exec-6]
com.ui.exceptions.SiteDownException
at com.ui.backend.Backend$$EOMu30qx.getResponse(Backend.groovy:118)
at com.ui.backend.Backend$$EOMu30qx.getResponseAsDomainObject(Backend.groovy:41)
at com.ui.contact.ContactService.detail(ContactService.groovy:166)
at com.ui.contact.ContactController.detail(ContactController.groovy:87)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
>>>> site down <<<<
Spot on, but for AJAX requests...
[11/11/13 16:54:09.380 error] SiteDownException occurred when processing request: [POST] /portal/contact/searchBody
Stacktrace follows: [org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver http-bio-8080-exec-7]
com.ui.exceptions.SiteDownException
at com.ui.backend.Backend$$EOMu30qx.getResponse(Backend.groovy:118)
at com.ui.backend.Backend$$EOMu30qx.getResponseAsDomainObject(Backend.groovy:41)
at com.ui.contact.ContactService.searchBody(ContactService.groovy:55)
at com.ui.contact.ContactController.searchBody(ContactController.groovy:23)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
>>>> site down <<<<
>>>> 500 <<<<
The last bit is key - it displays the "site down" message from the siteDown action, and "500" from the catch all error500 action.
Can anyone help explain why are both mappings being called for AJAX errors? Thanks
I've found the problem. I had an error trap in the jQuery AJAX wrapper:
error: function(XMLHttpRequest,textStatus,errorThrown){
window.location.href = config.contextPath + '/error/error500'; // Error - show the 500 error page
}
So the SiteDownException was correctly firing the SiteDown mapping, then the AJAX error handler was firing error500 mapping.
Related
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);
I don't know if anyone else is getting these messages, but I get these messages in the logs when the app goes into the background, then comes back:
[] nw_read_request_report [C3] Receive failed with error "Software caused connection abort"
Followed by:
Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
This is coming after many other bad logs, like:
[Process] kill() returned unexpected error 1 AND ProcessAssertion::processAssertionWasInvalidated()
Can't end BackgroundTask: no background task exists with identifier *, or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
My project has Firebase, which could be a source of all the web-related logs.
What could be causing it? Is it a bug?
Update
I removed errors from bullet no.1, written in my answer here.
I have the same issue with Facebook SDK login. Resolve it adding the following code in SceneDelegate.swift
import FBSDKCoreKit
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let openURLContext = URLContexts.first {
ApplicationDelegate.shared.application(UIApplication.shared, open:
openURLContext.url, sourceApplication:
openURLContext.options.sourceApplication, annotation:
openURLContext.options.annotation)
}
}
This is somewhat related, and hope it helps someone. My situation was that the openURL extra function provided in the SceneDelegate was not being called after returning from Facebook Authentication.
The solution was using
.onOpenURL { (url) in
ApplicationDelegate.shared.application(
UIApplication.shared,
open: url,
sourceApplication: nil,
annotation: [UIApplication.OpenURLOptionsKey.annotation]
)
}
On a view in the Scene instance, like so:
var body: some Scene {
WindowGroup {
LoadingView()
.onOpenURL { (url) in
ApplicationDelegate.shared.application(
UIApplication.shared,
open: url,
sourceApplication: nil,
annotation: [UIApplication.OpenURLOptionsKey.annotation]
)
}
}
}
This then calls the function in my extra application delegate, which then dismissed the login screen properly.
I had these errors. They were caused by my failure to call invalidateAndCancel on a NSURLSession.
I Had the same problem using Alamofire, it causes problem with request to confirm email
If you have the same issue - wait nearly 2 seconds to do you network response via Alamofire
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
Your network response
}
I have deployed Restful Web Serivce on the server and accessing it from Client application.
I am using JSON to communicate data between services & client.
Normal flow is working perfect.
But,in case of Exception, I am able to receive HTTP STATUS & reason for Exception but not receiving Response Body.
Here is my Exception Handler
#ExceptionHandler(MyException.class)
#ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR,reason="Unable to fetch data")
public #ResponseBody String handle(MyException ex)
{
ErrorInfo error = new ErrorInfo();
String response = null;
error.setErrorStatus(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR));
error.setErrorCode(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR)); // TODO Need to store Application specific error code
error.setErrorMessage("Communication Error : Unable to fetch conference data"); // TODO Need to get from message resource file
error.setDeveloperMessage(ex.getLocalizedMessage());
response = utilities.fromBeanToJson(error);
System.out.println("***Response : " + response);
return response; // Not able to receive this info
}
Actual Response :
<html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - Unable to fetch conference data</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Unable to fetch data</u></p><p><b>description</b> <u>The server encountered an internal error (Unable to fetch data) that prevented it from fulfilling this request.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></html>
You need to remove the reason from #ResponseStatus.
This is needed because from the the Javadoc of #ResponseStatus we can see:
The reason to be used for the response. If this element is not set,
it will default to the standard status message for the status code.
Note that due to the use of {#code HttpServletResponse.sendError(int,
String)}, the response will be considered complete and should not be
written to any further.
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.
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.