Java tutorial
/* * Copyright 2017 StreamSets Inc. * * 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 com.streamsets.datacollector.execution.alerts; import com.google.common.base.Strings; import com.streamsets.datacollector.config.AuthenticationType; import com.streamsets.datacollector.config.PipelineWebhookConfig; import com.streamsets.datacollector.config.WebhookCommonConfig; import com.streamsets.datacollector.creation.PipelineConfigBean; import com.streamsets.datacollector.execution.PipelineState; import com.streamsets.datacollector.execution.StateEventListener; import com.streamsets.datacollector.json.ObjectMapperFactory; import com.streamsets.datacollector.main.RuntimeInfo; import com.streamsets.datacollector.metrics.MetricsConfigurator; import com.streamsets.datacollector.restapi.bean.MeterJson; import com.streamsets.datacollector.restapi.bean.MetricRegistryJson; import com.streamsets.datacollector.runner.PipelineRuntimeException; import com.streamsets.dc.execution.manager.standalone.ThreadUsage; import com.streamsets.pipeline.api.ExecutionMode; import com.streamsets.pipeline.api.StageException; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Response; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; public class WebHookNotifier implements StateEventListener { private static final Logger LOG = LoggerFactory.getLogger(WebHookNotifier.class); private final String pipelineId; private final String pipelineTitle; private final String rev; private final PipelineConfigBean pipelineConfigBean; private final RuntimeInfo runtimeInfo; private Set<String> pipelineStates; private Map<String, Object> runtimeParameters; public WebHookNotifier(String pipelineId, String pipelineTitle, String rev, PipelineConfigBean pipelineConfigBean, RuntimeInfo runtimeInfo, Map<String, Object> runtimeParameters) { this.pipelineId = pipelineId; this.pipelineTitle = pipelineTitle; this.rev = rev; this.pipelineConfigBean = pipelineConfigBean; this.runtimeInfo = runtimeInfo; this.runtimeParameters = runtimeParameters; pipelineStates = new HashSet<>(); for (com.streamsets.datacollector.config.PipelineState s : pipelineConfigBean.notifyOnStates) { pipelineStates.add(s.name()); } } public String getPipelineId() { return pipelineId; } public String getRev() { return rev; } @Override public void onStateChange(PipelineState fromState, PipelineState toState, String toStateJson, ThreadUsage threadUsage, Map<String, String> offset) throws PipelineRuntimeException { //should not be active in slave mode if (toState.getExecutionMode() != ExecutionMode.SLAVE && pipelineId.equals(toState.getPipelineId())) { if (pipelineStates != null && pipelineStates.contains(toState.getStatus().name())) { for (PipelineWebhookConfig webhookConfig : pipelineConfigBean.webhookConfigs) { if (!StringUtils.isEmpty(webhookConfig.webhookUrl)) { Response response = null; try { DateFormat dateTimeFormat = new SimpleDateFormat(EmailConstants.DATE_MASK, Locale.ENGLISH); String payload = webhookConfig.payload .replace(WebhookConstants.PIPELINE_TITLE_KEY, Strings.nullToEmpty(pipelineTitle)) .replace(WebhookConstants.PIPELINE_URL_KEY, Strings.nullToEmpty( runtimeInfo.getBaseHttpUrl() + EmailConstants.PIPELINE_URL + toState.getPipelineId().replaceAll(" ", "%20"))) .replace(WebhookConstants.PIPELINE_STATE_KEY, Strings.nullToEmpty(toState.getStatus().toString())) .replace(WebhookConstants.TIME_KEY, dateTimeFormat.format(new Date(toState.getTimeStamp()))) .replace(WebhookConstants.PIPELINE_STATE_MESSAGE_KEY, Strings.nullToEmpty(toState.getMessage())) .replace(WebhookConstants.PIPELINE_RUNTIME_PARAMETERS_KEY, Strings.nullToEmpty(StringEscapeUtils.escapeJson(ObjectMapperFactory .get().writeValueAsString(runtimeParameters)))) .replace(WebhookConstants.PIPELINE_METRICS_KEY, Strings .nullToEmpty(StringEscapeUtils.escapeJson(toState.getMetrics()))); if (payload.contains(WebhookConstants.PIPELINE_INPUT_RECORDS_COUNT_KEY) || payload.contains(WebhookConstants.PIPELINE_OUTPUT_RECORDS_COUNT_KEY) || payload.contains(WebhookConstants.PIPELINE_ERROR_RECORDS_COUNT_KEY) || payload.contains(WebhookConstants.PIPELINE_ERROR_MESSAGES_COUNT_KEY)) { long inputRecordsCount = 0; long outputRecordsCount = 0; long errorRecordsCount = 0; long errorMessagesCount = 0; if (toState.getMetrics() != null) { MetricRegistryJson metricRegistryJson = ObjectMapperFactory.get() .readValue(toState.getMetrics(), MetricRegistryJson.class); if (metricRegistryJson != null && metricRegistryJson.getMeters() != null) { MeterJson batchInputRecords = metricRegistryJson.getMeters().get( "pipeline.batchInputRecords" + MetricsConfigurator.METER_SUFFIX); if (batchInputRecords != null) { inputRecordsCount = batchInputRecords.getCount(); } MeterJson batchOutputRecords = metricRegistryJson.getMeters().get( "pipeline.batchOutputRecords" + MetricsConfigurator.METER_SUFFIX); if (batchOutputRecords != null) { outputRecordsCount = batchOutputRecords.getCount(); } MeterJson batchErrorRecords = metricRegistryJson.getMeters().get( "pipeline.batchErrorRecords" + MetricsConfigurator.METER_SUFFIX); if (batchErrorRecords != null) { errorRecordsCount = batchErrorRecords.getCount(); } MeterJson batchErrorMessagesRecords = metricRegistryJson.getMeters().get( "pipeline.batchErrorMessages" + MetricsConfigurator.METER_SUFFIX); if (batchErrorMessagesRecords != null) { errorMessagesCount = batchErrorMessagesRecords.getCount(); } } } payload = payload .replace(WebhookConstants.PIPELINE_INPUT_RECORDS_COUNT_KEY, inputRecordsCount + "") .replace(WebhookConstants.PIPELINE_OUTPUT_RECORDS_COUNT_KEY, outputRecordsCount + "") .replace(WebhookConstants.PIPELINE_ERROR_RECORDS_COUNT_KEY, errorRecordsCount + "") .replace(WebhookConstants.PIPELINE_ERROR_MESSAGES_COUNT_KEY, errorMessagesCount + ""); } WebTarget webTarget = ClientBuilder.newClient().target(webhookConfig.webhookUrl); configurePasswordAuth(webhookConfig, webTarget); Invocation.Builder builder = webTarget.request(); for (String headerKey : webhookConfig.headers.keySet()) { builder.header(headerKey, webhookConfig.headers.get(headerKey)); } response = builder.post(Entity.entity(payload, webhookConfig.contentType)); if (response.getStatus() != Response.Status.OK.getStatusCode()) { LOG.error("Error calling Webhook URL, status code '{}': {}", response.getStatus(), response.readEntity(String.class)); } } catch (Exception e) { LOG.error("Error calling Webhook URL : {}", e.toString(), e); } finally { if (response != null) { response.close(); } } } } } } } private void configurePasswordAuth(WebhookCommonConfig webhookConfig, WebTarget webTarget) throws StageException { if (webhookConfig.authType == AuthenticationType.BASIC) { webTarget.register( HttpAuthenticationFeature.basic(webhookConfig.username.get(), webhookConfig.password.get())); } if (webhookConfig.authType == AuthenticationType.DIGEST) { webTarget.register( HttpAuthenticationFeature.digest(webhookConfig.username.get(), webhookConfig.password.get())); } if (webhookConfig.authType == AuthenticationType.UNIVERSAL) { webTarget.register(HttpAuthenticationFeature.universal(webhookConfig.username.get(), webhookConfig.password.get())); } } }