/** * Copyright 2016 LinkedIn Corp. 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. */ package com.linkedin.kmf.apps; import com.linkedin.kmf.apps.configs.MultiClusterMonitorConfig; import com.linkedin.kmf.services.ConsumeService; import com.linkedin.kmf.services.MultiClusterTopicManagementService; import com.linkedin.kmf.services.ProduceService; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /* * The MultiClusterMonitor app is intended to monitor the performance and availability of a pipeline of one * or more Kafka clusters. It creates one producer and one consumer with the given configuration, produces messages with increasing * integer in the message payload, consumes messages, and keeps track of the number of lost messages, duplicate messages, end-to-end * latency etc. Furthermore, MultiClusterMonitor use MultiClusterTopicManagementService to manage the monitor topics * across Kafka clusters and make sure they have the same number of partitions. */ public class MultiClusterMonitor implements App { private static final Logger LOG = LoggerFactory.getLogger(MultiClusterMonitor.class); private final MultiClusterTopicManagementService _topicManagementService; private final ProduceService _produceService; private final ConsumeService _consumeService; private final String _name; public MultiClusterMonitor(Map<String, Object> props, String name) throws Exception { _name = name; MultiClusterMonitorConfig config = new MultiClusterMonitorConfig(props); _topicManagementService = new MultiClusterTopicManagementService(createMultiClusterTopicManagementServiceProps(props, config), name); _produceService = new ProduceService(createProduceServiceProps(props, config), name); _consumeService = new ConsumeService(createConsumeServiceProps(props, config), name); } @SuppressWarnings("unchecked") private Map<String, Object> createProduceServiceProps(Map<String, Object> props, MultiClusterMonitorConfig config) { Map<String, Object> serviceProps = props.containsKey(MultiClusterMonitorConfig.PRODUCE_SERVICE_CONFIG) ? (Map) props.get(MultiClusterMonitorConfig.PRODUCE_SERVICE_CONFIG) : new HashMap<>(); serviceProps.put(MultiClusterMonitorConfig.TOPIC_CONFIG, config.getString(MultiClusterMonitorConfig.TOPIC_CONFIG)); return serviceProps; } @SuppressWarnings("unchecked") private Map<String, Object> createConsumeServiceProps(Map<String, Object> props, MultiClusterMonitorConfig config) { Map<String, Object> serviceProps = props.containsKey(MultiClusterMonitorConfig.CONSUME_SERVICE_CONFIG) ? (Map) props.get(MultiClusterMonitorConfig.CONSUME_SERVICE_CONFIG) : new HashMap<>(); serviceProps.put(MultiClusterMonitorConfig.TOPIC_CONFIG, config.getString(MultiClusterMonitorConfig.TOPIC_CONFIG)); return serviceProps; } @SuppressWarnings("unchecked") private Map<String, Object> createMultiClusterTopicManagementServiceProps(Map<String, Object> props, MultiClusterMonitorConfig config) { Map<String, Object> serviceProps = new HashMap<>(); serviceProps.put(MultiClusterMonitorConfig.TOPIC_MANAGEMENT_SERVICE_CONFIG, props.get(MultiClusterMonitorConfig.TOPIC_MANAGEMENT_SERVICE_CONFIG)); serviceProps.put(MultiClusterMonitorConfig.TOPIC_CONFIG, config.getString(MultiClusterMonitorConfig.TOPIC_CONFIG)); return serviceProps; } @Override public void start() { _topicManagementService.start(); _produceService.start(); _consumeService.start(); LOG.info(_name + "/MultiClusterMonitor started"); } @Override public void stop() { _topicManagementService.stop(); _produceService.stop(); _consumeService.stop(); LOG.info(_name + "/MultiClusterMonitor stopped"); } @Override public boolean isRunning() { return _topicManagementService.isRunning() && _produceService.isRunning() && _consumeService.isRunning(); } @Override public void awaitShutdown() { _topicManagementService.awaitShutdown(); _produceService.awaitShutdown(); _consumeService.awaitShutdown(); } }