fix #2448 slack notification

This commit is contained in:
Shinsuke Sugaya 2020-04-24 22:45:42 +09:00
parent b959b48eb8
commit 855adb6520
8 changed files with 172 additions and 33 deletions

View file

@ -136,6 +136,8 @@ public class Constants extends CoreLibConstants {
public static final String NOTIFICATION_TO_PROPERTY = "notification.to";
public static final String SLACK_WEBHOOK_URLS_PROPERTY = "slack.webhook.urls";
public static final String USE_BROWSER_LOCALE_FOR_SEARCH_PROPERTY = "search.use.browser.locale";
public static final String SUGGEST_SEARCH_LOG_PROPERTY = "suggest.searchlog";

View file

@ -53,6 +53,7 @@ import org.codelibs.fess.exception.ContainerNotAvailableException;
import org.codelibs.fess.helper.CrawlingInfoHelper;
import org.codelibs.fess.helper.DataIndexHelper;
import org.codelibs.fess.helper.DuplicateHostHelper;
import org.codelibs.fess.helper.NotificationHelper;
import org.codelibs.fess.helper.PathMappingHelper;
import org.codelibs.fess.helper.WebFsIndexHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
@ -60,6 +61,7 @@ import org.codelibs.fess.mylasta.mail.CrawlerPostcard;
import org.codelibs.fess.timer.SystemMonitorTarget;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.ThreadDumpUtil;
import org.dbflute.mail.send.hook.SMailCallbackContext;
import org.elasticsearch.monitor.jvm.JvmInfo;
import org.elasticsearch.monitor.os.OsProbe;
import org.elasticsearch.monitor.process.ProcessProbe;
@ -378,9 +380,7 @@ public class Crawler {
protected void sendMail(final Map<String, String> infoMap) {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final String toStrs = fessConfig.getNotificationTo();
if (StringUtil.isNotBlank(toStrs)) {
final String[] toAddresses = toStrs.split(",");
if (fessConfig.hasNotification()) {
final Map<String, String> dataMap = new HashMap<>();
for (final Map.Entry<String, String> entry : infoMap.entrySet()) {
dataMap.put(StringUtil.decapitalize(entry.getKey()), entry.getValue());
@ -395,34 +395,52 @@ public class Crawler {
logger.debug("\ninfoMap: {}\ndataMap: {}", infoMap, dataMap);
final DynamicProperties systemProperties = ComponentUtil.getSystemProperties();
final String toStrs = fessConfig.getNotificationTo();
final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
CrawlerPostcard.droppedInto(postbox, postcard -> {
postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
postcard.addReplyTo(fessConfig.getMailReturnPath());
stream(toAddresses).of(stream -> stream.forEach(address -> {
postcard.addTo(address);
}));
postcard.setCrawlerEndTime(getValueFromMap(dataMap, "crawlerEndTime", StringUtil.EMPTY));
postcard.setCrawlerExecTime(getValueFromMap(dataMap, "crawlerExecTime", "0"));
postcard.setCrawlerStartTime(getValueFromMap(dataMap, "crawlerStartTime", StringUtil.EMPTY));
postcard.setDataCrawlEndTime(getValueFromMap(dataMap, "dataCrawlEndTime", StringUtil.EMPTY));
postcard.setDataCrawlExecTime(getValueFromMap(dataMap, "dataCrawlExecTime", "0"));
postcard.setDataCrawlStartTime(getValueFromMap(dataMap, "dataCrawlStartTime", StringUtil.EMPTY));
postcard.setDataIndexSize(getValueFromMap(dataMap, "dataIndexSize", "0"));
postcard.setDataIndexExecTime(getValueFromMap(dataMap, "dataIndexExecTime", "0"));
postcard.setHostname(getValueFromMap(dataMap, "hostname", StringUtil.EMPTY));
postcard.setWebFsCrawlEndTime(getValueFromMap(dataMap, "webFsCrawlEndTime", StringUtil.EMPTY));
postcard.setWebFsCrawlExecTime(getValueFromMap(dataMap, "webFsCrawlExecTime", "0"));
postcard.setWebFsCrawlStartTime(getValueFromMap(dataMap, "webFsCrawlStartTime", StringUtil.EMPTY));
postcard.setWebFsIndexExecTime(getValueFromMap(dataMap, "webFsIndexExecTime", "0"));
postcard.setWebFsIndexSize(getValueFromMap(dataMap, "webFsIndexSize", "0"));
if (Constants.TRUE.equalsIgnoreCase(infoMap.get(Constants.CRAWLER_STATUS))) {
postcard.setStatus(Constants.OK);
try {
final String[] toAddresses;
if (StringUtil.isNotBlank(toStrs)) {
toAddresses = toStrs.split(",");
} else {
postcard.setStatus(Constants.FAIL);
toAddresses = StringUtil.EMPTY_STRINGS;
}
postcard.setJobname(systemProperties.getProperty("job.runtime.name", StringUtil.EMPTY));
});
final NotificationHelper notificationHelper = ComponentUtil.getNotificationHelper();
SMailCallbackContext.setPreparedMessageHookOnThread(notificationHelper::send);
CrawlerPostcard.droppedInto(postbox, postcard -> {
postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
postcard.addReplyTo(fessConfig.getMailReturnPath());
if (toAddresses.length > 0) {
stream(toAddresses).of(stream -> stream.map(String::trim).forEach(address -> {
postcard.addTo(address);
}));
} else {
postcard.addTo(fessConfig.getMailFromAddress());
postcard.dryrun();
}
postcard.setCrawlerEndTime(getValueFromMap(dataMap, "crawlerEndTime", StringUtil.EMPTY));
postcard.setCrawlerExecTime(getValueFromMap(dataMap, "crawlerExecTime", "0"));
postcard.setCrawlerStartTime(getValueFromMap(dataMap, "crawlerStartTime", StringUtil.EMPTY));
postcard.setDataCrawlEndTime(getValueFromMap(dataMap, "dataCrawlEndTime", StringUtil.EMPTY));
postcard.setDataCrawlExecTime(getValueFromMap(dataMap, "dataCrawlExecTime", "0"));
postcard.setDataCrawlStartTime(getValueFromMap(dataMap, "dataCrawlStartTime", StringUtil.EMPTY));
postcard.setDataIndexSize(getValueFromMap(dataMap, "dataIndexSize", "0"));
postcard.setDataIndexExecTime(getValueFromMap(dataMap, "dataIndexExecTime", "0"));
postcard.setHostname(getValueFromMap(dataMap, "hostname", StringUtil.EMPTY));
postcard.setWebFsCrawlEndTime(getValueFromMap(dataMap, "webFsCrawlEndTime", StringUtil.EMPTY));
postcard.setWebFsCrawlExecTime(getValueFromMap(dataMap, "webFsCrawlExecTime", "0"));
postcard.setWebFsCrawlStartTime(getValueFromMap(dataMap, "webFsCrawlStartTime", StringUtil.EMPTY));
postcard.setWebFsIndexExecTime(getValueFromMap(dataMap, "webFsIndexExecTime", "0"));
postcard.setWebFsIndexSize(getValueFromMap(dataMap, "webFsIndexSize", "0"));
if (Constants.TRUE.equalsIgnoreCase(infoMap.get(Constants.CRAWLER_STATUS))) {
postcard.setStatus(Constants.OK);
} else {
postcard.setStatus(Constants.FAIL);
}
postcard.setJobname(systemProperties.getProperty("job.runtime.name", StringUtil.EMPTY));
});
} finally {
SMailCallbackContext.clearPreparedMessageHookOnThread();
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright 2012-2020 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.helper;
import java.io.IOException;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.stream.StreamUtil;
import org.codelibs.curl.Curl;
import org.codelibs.curl.CurlResponse;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.mail.CardView;
import org.dbflute.mail.send.supplement.SMailPostingDiscloser;
public class NotificationHelper {
private static final Logger logger = LogManager.getLogger(NotificationHelper.class);
protected static final String LF = "\n";
public void send(final CardView cardView, final SMailPostingDiscloser discloser) {
sendToSlack(cardView, discloser);
}
protected void sendToSlack(CardView cardView, SMailPostingDiscloser discloser) {
// https://api.slack.com/messaging/webhooks#posting_with_webhooks
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final String slackWebhookUrls = fessConfig.getSlackWebhookUrls();
if (StringUtil.isBlank(slackWebhookUrls)) {
return;
}
final StringBuilder buf = new StringBuilder();
final String body =
buf.append("{\"text\":\"").append(StringEscapeUtils.escapeJson(toSlackMessage(discloser))).append("\"}").toString();
StreamUtil.split(slackWebhookUrls, "[,\\s]").of(
stream -> stream.filter(StringUtil::isNotBlank).forEach(
url -> {
try (CurlResponse response = Curl.post(url).header("Content-Type", "application/json").body(body).execute()) {
if (response.getHttpStatusCode() == 200) {
if (logger.isDebugEnabled()) {
logger.debug("Sent {} to {}.", body, url);
}
} else {
logger.warn("Failed to send {} to {}. HTTP Status is {}. {}", body, url, response.getHttpStatusCode(),
response.getContentAsString());
}
} catch (final IOException e) {
logger.warn("Failed to send {} to {}.", body, url, e);
}
}));
}
protected String toSlackMessage(final SMailPostingDiscloser discloser) {
final StringBuilder sb = new StringBuilder();
sb.append(LF).append(discloser.getSavedSubject().orElse(StringUtil.EMPTY).trim());
sb.append(LF).append("```");
sb.append(LF).append(discloser.getSavedPlainText().orElse(StringUtil.EMPTY).trim());
sb.append(LF).append("```");
return sb.toString();
}
}

View file

@ -15,15 +15,19 @@
*/
package org.codelibs.fess.job;
import static org.codelibs.core.stream.StreamUtil.stream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.entity.PingResponse;
import org.codelibs.fess.es.client.FessEsClient;
import org.codelibs.fess.helper.NotificationHelper;
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.dbflute.mail.send.hook.SMailCallbackContext;
import org.lastaflute.core.mail.Postbox;
public class PingEsJob {
@ -37,23 +41,40 @@ public class PingEsJob {
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)) {
if (fessConfig.hasNotification()) {
final String toStrs = fessConfig.getNotificationTo();
final String[] toAddresses;
if (StringUtil.isNotBlank(toStrs)) {
toAddresses = toStrs.split(",");
} else {
toAddresses = StringUtil.EMPTY_STRINGS;
}
final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
try {
final NotificationHelper notificationHelper = ComponentUtil.getNotificationHelper();
SMailCallbackContext.setPreparedMessageHookOnThread(notificationHelper::send);
EsStatusPostcard.droppedInto(postbox, postcard -> {
postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
postcard.addReplyTo(fessConfig.getMailReturnPath());
postcard.addTo(notificationTo);
if (toAddresses.length > 0) {
stream(toAddresses).of(stream -> stream.map(String::trim).forEach(address -> {
postcard.addTo(address);
}));
} else {
postcard.addTo(fessConfig.getMailFromAddress());
postcard.dryrun();
}
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);
} finally {
SMailCallbackContext.clearPreparedMessageHookOnThread();
}
}
resultBuf.append("Status of ").append(ping.getClusterName()).append(" is changed to ").append(ping.getClusterStatus())

View file

@ -501,6 +501,18 @@ public interface FessProp {
return getSystemProperty(Constants.PURGE_BY_BOTS_PROPERTY, Constants.DEFAULT_PURGE_BY_BOTS);
}
default boolean hasNotification() {
return StringUtil.isNotBlank(getNotificationTo()) || StringUtil.isNotBlank(getSlackWebhookUrls());
}
default void getSlackWebhookUrls(final String value) {
setSystemProperty(Constants.SLACK_WEBHOOK_URLS_PROPERTY, value);
}
default String getSlackWebhookUrls() {
return getSystemProperty(Constants.SLACK_WEBHOOK_URLS_PROPERTY, StringUtil.EMPTY);
}
default void setNotificationTo(final String value) {
setSystemProperty(Constants.NOTIFICATION_TO_PROPERTY, value);
}

View file

@ -82,7 +82,6 @@ public class FessMailDeliveryDepartmentCreator {
}
protected SMailDogmaticPostalPersonnel createDogmaticPostalPersonnel() { // #ext_point e.g. locale, database
final String testPrefix = fessConfig.getMailSubjectTestPrefix();
final AsyncManager asyncManager = getAsyncManager();
final MessageManager messageManager = getMessageManager();
return new SMailDogmaticPostalPersonnel() {
@ -96,7 +95,7 @@ public class FessMailDeliveryDepartmentCreator {
@Override
protected OptionalThing<SMailSubjectFilter> createSubjectFilter() {
return OptionalThing.of((view, subject) -> testPrefix + subject);
return OptionalThing.of((view, subject) -> subject);
}
@Override

View file

@ -51,6 +51,7 @@ import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.KeyMatchHelper;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.LanguageHelper;
import org.codelibs.fess.helper.NotificationHelper;
import org.codelibs.fess.helper.PathMappingHelper;
import org.codelibs.fess.helper.PermissionHelper;
import org.codelibs.fess.helper.PluginHelper;
@ -93,6 +94,8 @@ public final class ComponentUtil {
private static Map<String, Object> componentMap = new HashMap<>();
private static final String NOTIFICATION_HELPER = "notificationHelper";
private static final String SEARCH_HELPER = "searchHelper";
private static final String THEME_HELPER = "themeHelper";
@ -467,6 +470,10 @@ public final class ComponentUtil {
return getComponent(SEARCH_HELPER);
}
public static NotificationHelper getNotificationHelper() {
return getComponent(NOTIFICATION_HELPER);
}
public static <T> T getComponent(final Class<T> clazz) {
try {
return SingletonLaContainer.getComponent(clazz);

View file

@ -31,6 +31,8 @@
</component>
<component name="indexingHelper" class="org.codelibs.fess.helper.IndexingHelper">
</component>
<component name="notificationHelper" class="org.codelibs.fess.helper.NotificationHelper">
</component>
<component name="pathMappingHelper" class="org.codelibs.fess.helper.PathMappingHelper">
</component>
<component name="processHelper" class="org.codelibs.fess.helper.ProcessHelper">