diff --git a/src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java b/src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java index 7a0fbe28a..54759c589 100644 --- a/src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java +++ b/src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java @@ -23,10 +23,13 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.UUID; import javax.servlet.http.HttpServletResponse; import org.apache.commons.text.StringEscapeUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.codelibs.core.CoreLibConstants; import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; @@ -37,6 +40,8 @@ import org.lastaflute.web.util.LaResponseUtil; public abstract class BaseJsonApiManager extends BaseApiManager { + private static final Logger logger = LogManager.getLogger(BaseJsonApiManager.class); + protected String mimeType = "application/json"; protected void writeJsonResponse(final int status, final String body, final Throwable t) { @@ -57,13 +62,24 @@ public abstract class BaseJsonApiManager extends BaseApiManager { } else { sb.append(t.getMessage()); } - final StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - sb.append(" [ ").append(sw.toString()).append(" ]"); - try { - sw.close(); + try (final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw)) { + t.printStackTrace(pw); + pw.flush(); + sb.append(" [ ").append(sw.toString()).append(" ]"); } catch (final IOException ignore) {} - writeJsonResponse(status, body, sb.toString()); + final String message; + if (Constants.TRUE.equalsIgnoreCase(ComponentUtil.getFessConfig().getApiJsonResponseExceptionIncluded())) { + message = sb.toString(); + } else { + final String errorCode = UUID.randomUUID().toString(); + message = "error_code:" + errorCode; + if (logger.isDebugEnabled()) { + logger.debug("[{}] {}", errorCode, sb.toString().replace("\n", "\\n")); + } else { + logger.warn("[{}] {}", errorCode, t.getMessage()); + } + } + writeJsonResponse(status, body, message); } protected void writeJsonResponse(final int status, final String body, final String errMsg) { diff --git a/src/main/java/org/codelibs/fess/entity/PingResponse.java b/src/main/java/org/codelibs/fess/entity/PingResponse.java index 9f71a6f4c..771166972 100644 --- a/src/main/java/org/codelibs/fess/entity/PingResponse.java +++ b/src/main/java/org/codelibs/fess/entity/PingResponse.java @@ -19,11 +19,13 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Locale; +import java.util.Set; -import org.apache.commons.text.StringEscapeUtils; import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; +import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.SearchEngineUtil; +import org.lastaflute.di.exception.IORuntimeException; import org.opensearch.action.admin.cluster.health.ClusterHealthResponse; import org.opensearch.cluster.health.ClusterHealthStatus; import org.opensearch.common.xcontent.XContentType; @@ -57,23 +59,54 @@ public class PingResponse { status = response.getStatus() == ClusterHealthStatus.RED ? 1 : 0; clusterName = response.getClusterName(); clusterStatus = response.getStatus().toString(); + final Set fieldSet = ComponentUtil.getFessConfig().getApiPingEsFieldSet(); try (OutputStream out = SearchEngineUtil.getXContentBuilderOutputStream((builder, params) -> { builder.startObject(); - builder.field(CLUSTER_NAME, response.getClusterName()); - builder.field(STATUS, response.getStatus().name().toLowerCase(Locale.ROOT)); - builder.field(TIMED_OUT, response.isTimedOut()); - builder.field(NUMBER_OF_NODES, response.getNumberOfNodes()); - builder.field(NUMBER_OF_DATA_NODES, response.getNumberOfDataNodes()); - builder.field(ACTIVE_PRIMARY_SHARDS, response.getActivePrimaryShards()); - builder.field(ACTIVE_SHARDS, response.getActiveShards()); - builder.field(RELOCATING_SHARDS, response.getRelocatingShards()); - builder.field(INITIALIZING_SHARDS, response.getInitializingShards()); - builder.field(UNASSIGNED_SHARDS, response.getUnassignedShards()); - builder.field(DELAYED_UNASSIGNED_SHARDS, response.getDelayedUnassignedShards()); - builder.field(NUMBER_OF_PENDING_TASKS, response.getNumberOfPendingTasks()); - builder.field(NUMBER_OF_IN_FLIGHT_FETCH, response.getNumberOfInFlightFetch()); - builder.field(TASK_MAX_WAIT_TIME_IN_QUEUE_IN_MILLIS, response.getTaskMaxWaitingTime().getMillis()); - builder.field(ACTIVE_SHARDS_PERCENT_AS_NUMBER, response.getActiveShardsPercent()); + if (fieldSet.contains(CLUSTER_NAME)) { + builder.field(CLUSTER_NAME, response.getClusterName()); + } + if (fieldSet.contains(STATUS)) { + builder.field(STATUS, response.getStatus().name().toLowerCase(Locale.ROOT)); + } + if (fieldSet.contains(TIMED_OUT)) { + builder.field(TIMED_OUT, response.isTimedOut()); + } + if (fieldSet.contains(NUMBER_OF_NODES)) { + builder.field(NUMBER_OF_NODES, response.getNumberOfNodes()); + } + if (fieldSet.contains(NUMBER_OF_DATA_NODES)) { + builder.field(NUMBER_OF_DATA_NODES, response.getNumberOfDataNodes()); + } + if (fieldSet.contains(ACTIVE_PRIMARY_SHARDS)) { + builder.field(ACTIVE_PRIMARY_SHARDS, response.getActivePrimaryShards()); + } + if (fieldSet.contains(ACTIVE_SHARDS)) { + builder.field(ACTIVE_SHARDS, response.getActiveShards()); + } + if (fieldSet.contains(RELOCATING_SHARDS)) { + builder.field(RELOCATING_SHARDS, response.getRelocatingShards()); + } + if (fieldSet.contains(INITIALIZING_SHARDS)) { + builder.field(INITIALIZING_SHARDS, response.getInitializingShards()); + } + if (fieldSet.contains(UNASSIGNED_SHARDS)) { + builder.field(UNASSIGNED_SHARDS, response.getUnassignedShards()); + } + if (fieldSet.contains(DELAYED_UNASSIGNED_SHARDS)) { + builder.field(DELAYED_UNASSIGNED_SHARDS, response.getDelayedUnassignedShards()); + } + if (fieldSet.contains(NUMBER_OF_PENDING_TASKS)) { + builder.field(NUMBER_OF_PENDING_TASKS, response.getNumberOfPendingTasks()); + } + if (fieldSet.contains(NUMBER_OF_IN_FLIGHT_FETCH)) { + builder.field(NUMBER_OF_IN_FLIGHT_FETCH, response.getNumberOfInFlightFetch()); + } + if (fieldSet.contains(TASK_MAX_WAIT_TIME_IN_QUEUE_IN_MILLIS)) { + builder.field(TASK_MAX_WAIT_TIME_IN_QUEUE_IN_MILLIS, response.getTaskMaxWaitingTime().getMillis()); + } + if (fieldSet.contains(ACTIVE_SHARDS_PERCENT_AS_NUMBER)) { + builder.field(ACTIVE_SHARDS_PERCENT_AS_NUMBER, response.getActiveShardsPercent()); + } builder.endObject(); return builder; }, XContentType.JSON)) { @@ -82,7 +115,7 @@ public class PingResponse { message = "{}"; } } catch (final IOException e) { - message = "{ \"error\" : \"" + StringEscapeUtils.escapeJson(e.getMessage()) + "\"}"; + throw new IORuntimeException(e); } } diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java index 405eaad5b..efac6b648 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java @@ -250,6 +250,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction /** The key of the configuration. e.g. */ String API_JSON_RESPONSE_HEADERS = "api.json.response.headers"; + /** The key of the configuration. e.g. false */ + String API_JSON_RESPONSE_EXCEPTION_INCLUDED = "api.json.response.exception.included"; + /** The key of the configuration. e.g. */ String API_GSA_RESPONSE_HEADERS = "api.gsa.response.headers"; @@ -274,6 +277,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction /** The key of the configuration. e.g. false */ String API_JSONP_ENABLED = "api.jsonp.enabled"; + /** The key of the configuration. e.g. status,timed_out */ + String API_PING_ES_FIELDS = "api.ping.es.fields"; + /** The key of the configuration. e.g. */ String VIRTUAL_HOST_HEADERS = "virtual.host.headers"; @@ -2298,6 +2304,20 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction */ Integer getApiJsonResponseHeadersAsInteger(); + /** + * Get the value for the key 'api.json.response.exception.included'.
+ * The value is, e.g. false
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + */ + String getApiJsonResponseExceptionIncluded(); + + /** + * Is the property for the key 'api.json.response.exception.included' true?
+ * The value is, e.g. false
+ * @return The determination, true or false. (if not found, exception but basically no way) + */ + boolean isApiJsonResponseExceptionIncluded(); + /** * Get the value for the key 'api.gsa.response.headers'.
* The value is, e.g.
@@ -2392,6 +2412,13 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction */ boolean isApiJsonpEnabled(); + /** + * Get the value for the key 'api.ping.es.fields'.
+ * The value is, e.g. status,timed_out
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + */ + String getApiPingEsFields(); + /** * Get the value for the key 'virtual.host.headers'.
* The value is, e.g.
@@ -7645,6 +7672,14 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction return getAsInteger(FessConfig.API_JSON_RESPONSE_HEADERS); } + public String getApiJsonResponseExceptionIncluded() { + return get(FessConfig.API_JSON_RESPONSE_EXCEPTION_INCLUDED); + } + + public boolean isApiJsonResponseExceptionIncluded() { + return is(FessConfig.API_JSON_RESPONSE_EXCEPTION_INCLUDED); + } + public String getApiGsaResponseHeaders() { return get(FessConfig.API_GSA_RESPONSE_HEADERS); } @@ -7697,6 +7732,10 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction return is(FessConfig.API_JSONP_ENABLED); } + public String getApiPingEsFields() { + return get(FessConfig.API_PING_ES_FIELDS); + } + public String getVirtualHostHeaders() { return get(FessConfig.VIRTUAL_HOST_HEADERS); } @@ -10426,6 +10465,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction defaultMap.put(FessConfig.API_SEARCH_ACCEPT_REFERERS, ""); defaultMap.put(FessConfig.API_SEARCH_SCROLL, "false"); defaultMap.put(FessConfig.API_JSON_RESPONSE_HEADERS, ""); + defaultMap.put(FessConfig.API_JSON_RESPONSE_EXCEPTION_INCLUDED, "false"); defaultMap.put(FessConfig.API_GSA_RESPONSE_HEADERS, ""); defaultMap.put(FessConfig.API_DASHBOARD_RESPONSE_HEADERS, ""); defaultMap.put(FessConfig.API_CORS_ALLOW_ORIGIN, "*"); @@ -10434,6 +10474,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction defaultMap.put(FessConfig.API_CORS_ALLOW_HEADERS, "Origin, Content-Type, Accept, Authorization, X-Requested-With"); defaultMap.put(FessConfig.API_CORS_ALLOW_CREDENTIALS, "true"); defaultMap.put(FessConfig.API_JSONP_ENABLED, "false"); + defaultMap.put(FessConfig.API_PING_ES_FIELDS, "status,timed_out"); defaultMap.put(FessConfig.VIRTUAL_HOST_HEADERS, ""); defaultMap.put(FessConfig.HTTP_PROXY_HOST, ""); defaultMap.put(FessConfig.HTTP_PROXY_PORT, "8080"); diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java index 8cd0bb374..6753b6f00 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java @@ -70,6 +70,8 @@ import org.opensearch.search.sort.SortOrder; public interface FessProp { + String API_PING_ES_FIELD_SET = "apiPingEsFieldSet"; + String QUERY_HIGHLIGHT_TERMINAL_CHARS = "queryHighlightTerminalChars"; String QUERY_HIGHLIGHT_BOUNDARY_CHARS = "queryHighlightBoundaryChars"; @@ -2113,4 +2115,16 @@ public interface FessProp { return split(getSearchlogRequestHeaders(), ",") .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n])); } + + String getApiPingEsFields(); + + default Set getApiPingEsFieldSet() { + Set value = (Set) propMap.get(API_PING_ES_FIELD_SET); + if (value == null) { + value = split(getApiPingEsFields(), ",") + .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet())); + propMap.put(API_PING_ES_FIELD_SET, value); + } + return value; + } } diff --git a/src/main/resources/fess_config.properties b/src/main/resources/fess_config.properties index 8a94afad1..e22f73a62 100644 --- a/src/main/resources/fess_config.properties +++ b/src/main/resources/fess_config.properties @@ -170,6 +170,7 @@ api.admin.access.permissions=Radmin-api api.search.accept.referers= api.search.scroll=false api.json.response.headers= +api.json.response.exception.included=false api.gsa.response.headers= api.dashboard.response.headers= api.cors.allow.origin=* @@ -178,6 +179,7 @@ api.cors.max.age=3600 api.cors.allow.headers=Origin, Content-Type, Accept, Authorization, X-Requested-With api.cors.allow.credentials=true api.jsonp.enabled=false +api.ping.es.fields=status,timed_out # Virtual Host: Host:fess.codelibs.org=fess