Improve troubleshooting doc/flows
- Use better wording for unknown server error - Add basic troubleshooting doc
This commit is contained in:
@@ -74,6 +74,9 @@ Also, check [our FAQ entry](docs/faq.md#what-kind-of-setup-is-mxisd-really-desig
|
|||||||
See the [dedicated document](docs/getting-started.md)
|
See the [dedicated document](docs/getting-started.md)
|
||||||
|
|
||||||
# Support
|
# Support
|
||||||
|
## Troubleshooting
|
||||||
|
A basic troubleshooting guide is available [here](docs/troubleshooting.md).
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
Over Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io) ([Preview](https://view.matrix.org/room/!NPRUEisLjcaMtHIzDr:kamax.io/))
|
Over Matrix: [#mxisd:kamax.io](https://matrix.to/#/#mxisd:kamax.io) ([Preview](https://view.matrix.org/room/!NPRUEisLjcaMtHIzDr:kamax.io/))
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,8 @@ by the relevant hostname which you configured in your reverse proxy.
|
|||||||
**NOTE:** You might not see a suggestion for the e-mail address, which is normal. Still proceed with the invite.
|
**NOTE:** You might not see a suggestion for the e-mail address, which is normal. Still proceed with the invite.
|
||||||
|
|
||||||
If it worked, it means you are up and running and can enjoy mxisd in its basic mode! Congratulations!
|
If it worked, it means you are up and running and can enjoy mxisd in its basic mode! Congratulations!
|
||||||
If it did not work, [get in touch](../README.md#support) and we'll do our best to get you started.
|
If it did not work, read the basic [troubleshooting guide](troubleshooting.md), [get in touch](../README.md#support) and
|
||||||
|
we'll do our best to get you started.
|
||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
Once your mxisd server is up and running, there are several ways you can enhance and integrate further with your
|
Once your mxisd server is up and running, there are several ways you can enhance and integrate further with your
|
||||||
|
|||||||
53
docs/troubleshooting.md
Normal file
53
docs/troubleshooting.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Troubleshooting
|
||||||
|
- [Purpose](#purpose)
|
||||||
|
- [Logs](#logs)
|
||||||
|
- [Locations](#locations)
|
||||||
|
- [Reading Them](#reading-them)
|
||||||
|
- [Common issues](#common-issues)
|
||||||
|
- [Submit an issue](#submit-an-issue)
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This document describes basic troubleshooting steps for mxisd.
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
### Locations
|
||||||
|
mxisd logs to `STDOUT` (Standard Output) and `STDERR` (Standard Error) only, which gets redirected
|
||||||
|
to log file(s) depending on your system.
|
||||||
|
|
||||||
|
If you use the [Debian package](install/debian.md), this goes to `syslog`.
|
||||||
|
If you use the [Docker image](install/docker.md), this goes to the container logs.
|
||||||
|
|
||||||
|
For any other platform, please refer to your package maintainer.
|
||||||
|
|
||||||
|
### Reading them
|
||||||
|
Before reporting an issue, it is important to produce clean and complete logs so they can be understood.
|
||||||
|
|
||||||
|
It is usually useless to try to troubleshoot an issue based on a single log line. Any action or API request
|
||||||
|
in mxisd would trigger more than one log lines, and those would be considered necessary context to
|
||||||
|
understand what happened.
|
||||||
|
|
||||||
|
You may also find things called *stacktraces*. Those are important to pin-point bugs and the likes and should
|
||||||
|
always be included in any report. They also tend to be very specific about the issue at hand.
|
||||||
|
|
||||||
|
Example of a stacktrace:
|
||||||
|
```
|
||||||
|
Exception in thread "main" java.lang.NullPointerException
|
||||||
|
at com.example.myproject.Book.getTitle(Book.java:16)
|
||||||
|
at com.example.myproject.Author.getBookTitles(Author.java:25)
|
||||||
|
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common issues
|
||||||
|
#### Internal Server Error
|
||||||
|
`Contact your administrator with reference Transaction #123456789`
|
||||||
|
|
||||||
|
This is a generic message produced in case of an unknown error. The transaction reference allows to easily find
|
||||||
|
the location in the logs to look for an error.
|
||||||
|
|
||||||
|
**IMPORTANT:** That line alone does not tell you anything about the error. You'll need the log lines before and after,
|
||||||
|
usually including a stacktrace, to know what happened. Please take the time to read the surround output to get
|
||||||
|
context about the issue at hand.
|
||||||
|
|
||||||
|
## Submit an issue
|
||||||
|
In case the logs do not allow you to understand the issue at hand, please submit clean and complete logs
|
||||||
|
as explained [here](#reading-them) in a new issue on the repository, or [get in touch](../README.md#contact).
|
||||||
@@ -101,6 +101,10 @@ public abstract class BasicHttpHandler implements HttpHandler {
|
|||||||
return GsonUtil.parseObj(getBodyUtf8(exchange));
|
return GsonUtil.parseObj(getBodyUtf8(exchange));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void putHeader(HttpServerExchange ex, String name, String value) {
|
||||||
|
ex.getResponseHeaders().put(HttpString.tryFromString(name), value);
|
||||||
|
}
|
||||||
|
|
||||||
protected void respond(HttpServerExchange ex, int statusCode, JsonElement bodyJson) {
|
protected void respond(HttpServerExchange ex, int statusCode, JsonElement bodyJson) {
|
||||||
respondJson(ex, statusCode, GsonUtil.get().toJson(bodyJson));
|
respondJson(ex, statusCode, GsonUtil.get().toJson(bodyJson));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ import io.kamax.matrix.json.InvalidJsonException;
|
|||||||
import io.kamax.mxisd.exception.*;
|
import io.kamax.mxisd.exception.*;
|
||||||
import io.undertow.server.HttpHandler;
|
import io.undertow.server.HttpHandler;
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
import io.undertow.util.HttpString;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -37,15 +36,22 @@ import java.time.Instant;
|
|||||||
|
|
||||||
public class SaneHandler extends BasicHttpHandler {
|
public class SaneHandler extends BasicHttpHandler {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SaneHandler.class);
|
||||||
|
|
||||||
|
private static final String CorsOriginName = "Access-Control-Allow-Origin";
|
||||||
|
private static final String CorsOriginValue = "*";
|
||||||
|
private static final String CorsMethodsName = "Access-Control-Allow-Methods";
|
||||||
|
private static final String CorsMethodsValue = "GET, POST, PUT, DELETE, OPTIONS";
|
||||||
|
private static final String CorsHeadersName = "Access-Control-Allow-Headers";
|
||||||
|
private static final String CorsHeadersValue = "Origin, X-Requested-With, Content-Type, Accept, Authorization";
|
||||||
|
|
||||||
public static SaneHandler around(HttpHandler h) {
|
public static SaneHandler around(HttpHandler h) {
|
||||||
return new SaneHandler(h);
|
return new SaneHandler(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
private transient final Logger log = LoggerFactory.getLogger(SaneHandler.class);
|
private final HttpHandler child;
|
||||||
|
|
||||||
private HttpHandler child;
|
private SaneHandler(HttpHandler child) {
|
||||||
|
|
||||||
public SaneHandler(HttpHandler child) {
|
|
||||||
this.child = child;
|
this.child = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +64,9 @@ public class SaneHandler extends BasicHttpHandler {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// CORS headers as per spec
|
// CORS headers as per spec
|
||||||
exchange.getResponseHeaders().put(HttpString.tryFromString("Access-Control-Allow-Origin"), "*");
|
putHeader(exchange, CorsOriginName, CorsOriginValue);
|
||||||
exchange.getResponseHeaders().put(HttpString.tryFromString("Access-Control-Allow-Methods"), "GET, POST, PUT, DELETE, OPTIONS");
|
putHeader(exchange, CorsMethodsName, CorsMethodsValue);
|
||||||
exchange.getResponseHeaders().put(HttpString.tryFromString("Access-Control-Allow-Headers"), "Origin, X-Requested-With, Content-Type, Accept, Authorization");
|
putHeader(exchange, CorsHeadersName, CorsHeadersValue);
|
||||||
|
|
||||||
child.handleRequest(exchange);
|
child.handleRequest(exchange);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@@ -89,9 +95,9 @@ public class SaneHandler extends BasicHttpHandler {
|
|||||||
handleException(exchange, e);
|
handleException(exchange, e);
|
||||||
} catch (InternalServerError e) {
|
} catch (InternalServerError e) {
|
||||||
if (StringUtils.isNotBlank(e.getInternalReason())) {
|
if (StringUtils.isNotBlank(e.getInternalReason())) {
|
||||||
log.error("Reference #{} - {}", e.getReference(), e.getInternalReason());
|
log.error("Transaction #{} - {}", e.getReference(), e.getInternalReason());
|
||||||
} else {
|
} else {
|
||||||
log.error("Reference #{}", e);
|
log.error("Transaction #{}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleException(exchange, e);
|
handleException(exchange, e);
|
||||||
@@ -105,14 +111,11 @@ public class SaneHandler extends BasicHttpHandler {
|
|||||||
respond(exchange, e.getStatus(), buildErrorBody(exchange, e.getErrorCode(), e.getError()));
|
respond(exchange, e.getStatus(), buildErrorBody(exchange, e.getErrorCode(), e.getError()));
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
log.error("Unknown error when handling {}", exchange.getRequestURL(), e);
|
log.error("Unknown error when handling {}", exchange.getRequestURL(), e);
|
||||||
respond(exchange, HttpStatus.SC_INTERNAL_SERVER_ERROR, buildErrorBody(exchange,
|
String message = e.getMessage();
|
||||||
"M_UNKNOWN",
|
if (StringUtils.isBlank(message)) {
|
||||||
StringUtils.defaultIfBlank(
|
message = "An internal server error occurred. Contact your administrator with reference Transaction #" + Instant.now().toEpochMilli();
|
||||||
e.getMessage(),
|
}
|
||||||
"An internal server error occurred. If this error persists, please contact support with reference #" +
|
respond(exchange, HttpStatus.SC_INTERNAL_SERVER_ERROR, buildErrorBody(exchange, "M_UNKNOWN", message));
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
));
|
|
||||||
} finally {
|
} finally {
|
||||||
exchange.endExchange();
|
exchange.endExchange();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user