瀏覽代碼

fix #758 add PingEsJob

Shinsuke Sugaya 8 年之前
父節點
當前提交
ee77e15bff

+ 15 - 0
src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java

@@ -1,3 +1,18 @@
+/*
+ * Copyright 2012-2016 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
 package org.codelibs.fess.api;
 package org.codelibs.fess.api;
 
 
 import java.io.IOException;
 import java.io.IOException;

+ 9 - 2
src/main/java/org/codelibs/fess/api/json/JsonApiManager.java

@@ -15,6 +15,8 @@
  */
  */
 package org.codelibs.fess.api.json;
 package org.codelibs.fess.api.json;
 
 
+import static org.codelibs.core.stream.StreamUtil.stream;
+
 import java.io.IOException;
 import java.io.IOException;
 import java.net.URLDecoder;
 import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.ArrayList;
@@ -22,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 
 import javax.servlet.FilterChain;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.ServletException;
@@ -113,15 +116,19 @@ public class JsonApiManager extends BaseJsonApiManager {
         try {
         try {
             final PingResponse pingResponse = fessEsClient.ping();
             final PingResponse pingResponse = fessEsClient.ping();
             status = pingResponse.getStatus();
             status = pingResponse.getStatus();
+            String errMsg = null;
+            if (status != 0) {
+                errMsg = stream(pingResponse.getFailures()).get(stream -> stream.collect(Collectors.joining()));
+            }
+            writeJsonResponse(status, null, errMsg);
         } catch (final Exception e) {
         } catch (final Exception e) {
             status = 9;
             status = 9;
             err = e;
             err = e;
             if (logger.isDebugEnabled()) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Failed to process a ping request.", e);
                 logger.debug("Failed to process a ping request.", e);
             }
             }
+            writeJsonResponse(status, null, err);
         }
         }
-
-        writeJsonResponse(status, null, err);
     }
     }
 
 
     protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
     protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {

+ 23 - 1
src/main/java/org/codelibs/fess/entity/PingResponse.java

@@ -15,18 +15,40 @@
  */
  */
 package org.codelibs.fess.entity;
 package org.codelibs.fess.entity;
 
 
+import java.util.List;
+
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
 
 
 public class PingResponse {
 public class PingResponse {
-    private int status = 0;
+    private int status;
+
+    private List<String> failures;
+
+    private String clusterName;
+
+    private String clusterStatus;
 
 
     public PingResponse(final ClusterHealthResponse response) {
     public PingResponse(final ClusterHealthResponse response) {
         status = response.getStatus() == ClusterHealthStatus.RED ? 1 : 0;
         status = response.getStatus() == ClusterHealthStatus.RED ? 1 : 0;
+        failures = response.getValidationFailures();
+        clusterName = response.getClusterName();
+        clusterStatus = response.getStatus().toString();
     }
     }
 
 
     public int getStatus() {
     public int getStatus() {
         return status;
         return status;
     }
     }
 
 
+    public String[] getFailures() {
+        return failures.stream().toArray(n -> new String[n]);
+    }
+
+    public String getClusterName() {
+        return clusterName;
+    }
+
+    public String getClusterStatus() {
+        return clusterStatus;
+    }
 }
 }

+ 7 - 0
src/main/java/org/codelibs/fess/helper/SystemHelper.java

@@ -33,6 +33,7 @@ import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.annotation.PreDestroy;
@@ -75,6 +76,8 @@ public class SystemHelper {
 
 
     protected Random random = new SecureRandom();
     protected Random random = new SecureRandom();
 
 
+    protected AtomicInteger previousClusterState = new AtomicInteger(0);
+
     @PostConstruct
     @PostConstruct
     public void init() {
     public void init() {
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
@@ -313,4 +316,8 @@ public class SystemHelper {
         this.random = random;
         this.random = random;
     }
     }
 
 
+    public boolean isChangedClusterState(int status) {
+        return previousClusterState.getAndSet(status) != status;
+    }
+
 }
 }

+ 72 - 0
src/main/java/org/codelibs/fess/job/PingEsJob.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012-2016 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.job;
+
+import org.codelibs.core.lang.StringUtil;
+import org.codelibs.fess.entity.PingResponse;
+import org.codelibs.fess.es.client.FessEsClient;
+import org.codelibs.fess.helper.SystemHelper;
+import org.codelibs.fess.mylasta.direction.FessConfig;
+import org.codelibs.fess.mylasta.mail.EsStatusPostcard;
+import org.codelibs.fess.util.ComponentUtil;
+import org.lastaflute.core.mail.Postbox;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PingEsJob {
+
+    private static final Logger logger = LoggerFactory.getLogger(PingEsJob.class);
+
+    public String execute() {
+        final FessEsClient fessEsClient = ComponentUtil.getFessEsClient();
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
+
+        final StringBuilder resultBuf = new StringBuilder();
+
+        final String notificationTo = fessConfig.getNotificationTo();
+        final PingResponse ping = fessEsClient.ping();
+        final int status = ping.getStatus();
+        if (systemHelper.isChangedClusterState(status)) {
+            if (StringUtil.isNotBlank(notificationTo)) {
+                final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
+                try {
+                    EsStatusPostcard.droppedInto(postbox, postcard -> {
+                        postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
+                        postcard.addReplyTo(fessConfig.getMailReturnPath());
+                        postcard.addTo(notificationTo);
+                        postcard.setHostname(systemHelper.getHostname());
+                        postcard.setClustername(ping.getClusterName());
+                        postcard.setClusterstatus(ping.getClusterStatus());
+                    });
+                } catch (final Exception e) {
+                    logger.warn("Failed to send a test mail.", e);
+                }
+            }
+            resultBuf.append("Status of ").append(ping.getClusterName()).append(" is changed to ").append(ping.getClusterStatus())
+                    .append('.');
+        } else {
+            if (status == 0) {
+                resultBuf.append(ping.getClusterName()).append(" is alive.");
+            } else {
+                resultBuf.append(ping.getClusterName()).append(" is not available.");
+            }
+        }
+
+        return resultBuf.toString();
+    }
+
+}

+ 9 - 36
src/main/java/org/codelibs/fess/mylasta/mail/EsStatusPostcard.java

@@ -50,7 +50,7 @@ public class EsStatusPostcard extends LaTypicalPostcard {
 
 
     @Override
     @Override
     protected String[] getPropertyNames() {
     protected String[] getPropertyNames() {
-        return new String[] { "hostname", "server", "statusBefore", "statusAfter", "indexBefore", "indexAfter" };
+        return new String[] { "hostname", "clustername", "clusterstatus" };
     }
     }
 
 
     // ===================================================================================
     // ===================================================================================
@@ -108,47 +108,20 @@ public class EsStatusPostcard extends LaTypicalPostcard {
     }
     }
 
 
     /**
     /**
-     * Set the value of server, used in parameter comment. <br>
+     * Set the value of clustername, used in parameter comment. <br>
      * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
      * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
-     * @param server The parameter value of server. (NotNull)
+     * @param clustername The parameter value of clustername. (NotNull)
      */
      */
-    public void setServer(String server) {
-        registerVariable("server", server);
+    public void setClustername(String clustername) {
+        registerVariable("clustername", clustername);
     }
     }
 
 
     /**
     /**
-     * Set the value of statusBefore, used in parameter comment. <br>
+     * Set the value of clusterstatus, used in parameter comment. <br>
      * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
      * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
-     * @param statusBefore The parameter value of statusBefore. (NotNull)
+     * @param clusterstatus The parameter value of clusterstatus. (NotNull)
      */
      */
-    public void setStatusBefore(String statusBefore) {
-        registerVariable("statusBefore", statusBefore);
-    }
-
-    /**
-     * Set the value of statusAfter, used in parameter comment. <br>
-     * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
-     * @param statusAfter The parameter value of statusAfter. (NotNull)
-     */
-    public void setStatusAfter(String statusAfter) {
-        registerVariable("statusAfter", statusAfter);
-    }
-
-    /**
-     * Set the value of indexBefore, used in parameter comment. <br>
-     * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
-     * @param indexBefore The parameter value of indexBefore. (NotNull)
-     */
-    public void setIndexBefore(String indexBefore) {
-        registerVariable("indexBefore", indexBefore);
-    }
-
-    /**
-     * Set the value of indexAfter, used in parameter comment. <br>
-     * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
-     * @param indexAfter The parameter value of indexAfter. (NotNull)
-     */
-    public void setIndexAfter(String indexAfter) {
-        registerVariable("indexAfter", indexAfter);
+    public void setClusterstatus(String clusterstatus) {
+        registerVariable("clusterstatus", clusterstatus);
     }
     }
 }
 }

+ 2 - 0
src/main/resources/fess_indices/.fess_config/scheduled_job.bulk

@@ -10,3 +10,5 @@
 {"name":"Doc Purger","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeDocJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":5,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
 {"name":"Doc Purger","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeDocJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":5,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
 {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"thumbnail_purger"}}
 {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"thumbnail_purger"}}
 {"name":"Thumbnail Purger","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeThumbnailJob\").expiry(30 * 24 * 60 * 60 * 1000).execute();","jobLogging":true,"crawler":false,"available":true,"sortOrder":6,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
 {"name":"Thumbnail Purger","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeThumbnailJob\").expiry(30 * 24 * 60 * 60 * 1000).execute();","jobLogging":true,"crawler":false,"available":true,"sortOrder":6,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
+{"index":{"_index":".fess_config","_type":"scheduled_job","_id":"ping_es"}}
+{"name":"Ping Elasticsearch","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"pingEsJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":7,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}

+ 2 - 0
src/main/resources/fess_job.xml

@@ -18,4 +18,6 @@
 	</component>
 	</component>
 	<component name="purgeThumbnailJob" class="org.codelibs.fess.job.PurgeThumbnailJob" instance="prototype">
 	<component name="purgeThumbnailJob" class="org.codelibs.fess.job.PurgeThumbnailJob" instance="prototype">
 	</component>
 	</component>
+	<component name="pingEsJob" class="org.codelibs.fess.job.PingEsJob" instance="prototype">
+	</component>
 </components>
 </components>

+ 2 - 4
src/main/resources/mail/es_status.dfmail

@@ -4,11 +4,9 @@
 subject: [FESS] Status Change: /*pmb.hostname:orElse('Unknown')*/
 subject: [FESS] Status Change: /*pmb.hostname:orElse('Unknown')*/
 >>>
 >>>
 --- Server Info ---
 --- Server Info ---
+Cluster Name: /*pmb.clustername:orElse('Unknown')*/
 Host Name: /*pmb.hostname:orElse('Unknown')*/
 Host Name: /*pmb.hostname:orElse('Unknown')*/
 
 
-Elasticsearch: /*pmb.server*/
-
 --- Status ---
 --- Status ---
-/*IF pmb.statusBefore != null*/Status: /*pmb.statusBefore*/ -> /*pmb.statusAfter*//*END*/
-/*IF pmb.indexBefore != null*/Index: /*pmb.indexBefore*/ -> /*pmb.indexAfter*//*END*/
+Cluster Status: /*pmb.clusterstatus:orElse('Unknown')*/