浏览代码

fix #2682 add api.ping.es.fields and api.json.response.exception.included

Shinsuke Sugaya 2 年之前
父节点
当前提交
c64e957ce2

+ 22 - 6
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) {

+ 50 - 17
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<String> 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);
         }
     }
 

+ 41 - 0
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'. <br>
+     * The value is, e.g. false <br>
+     * @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? <br>
+     * The value is, e.g. false <br>
+     * @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'. <br>
      * The value is, e.g.  <br>
@@ -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'. <br>
+     * The value is, e.g. status,timed_out <br>
+     * @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'. <br>
      * The value is, e.g.  <br>
@@ -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");

+ 14 - 0
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<String> getApiPingEsFieldSet() {
+        Set<String> value = (Set<String>) 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;
+    }
 }

+ 2 - 0
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