package com.sf.monitor.druid;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sf.log.Logger;
import com.sf.monitor.Config;
import com.sf.monitor.Event;
import com.sf.monitor.Resources;
import com.sf.monitor.utils.DCMZkUtils;
import com.sf.monitor.utils.JsonValues;
import com.sf.monitor.utils.PrometheusUtils;
import com.sf.monitor.utils.Utils;
import org.joda.time.DateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class DruidInfos {
private static final Logger log = new Logger(DruidInfos.class);
private static final String coordinatorLeaderElectionPath = "/coordinator/_COORDINATOR";
private static final String overlordLeaderElectionPath = "/indexer/leaderLatchPath";
public static class AnnounceNode {
public String host;
public String name;
public String role;
public String regTime;
public String serviceType;
public static List<Map<String, Object>> toMaps(List<AnnounceNode> nodes) {
return Lists.transform(
nodes, new Function<AnnounceNode, Map<String, Object>>() {
@Override
public Map<String, Object> apply(AnnounceNode node) {
return ImmutableMap.of(
"host",
(Object) node.host,
"name",
node.name,
"role",
node.role,
"regTime",
node.regTime,
"serviceType",
node.serviceType
);
}
}
);
}
}
@JsonProperty
public String zkRootPath;
@JsonProperty
public String zkDiscoveryPath;
@JsonProperty
public String overlordName;
@JsonProperty
public String brokerName;
@JsonProperty
public String coordinatorName;
@JsonProperty
public String realtimeName;
@JsonProperty
public String historicalName;
@JsonProperty
public String middleManagerName;
@JsonProperty
public Map<String, Boolean> warningSpecs;
private DruidService<DruidService.OverlordService> overlordService;
private DruidService<DruidService.CoordinatorService> coordinatorService;
public boolean shouldWarn(String metric) {
if (warningSpecs == null) {
return false;
} else {
Boolean b = warningSpecs.get(metric);
return b == null ? false : b;
}
}
public void init() {
overlordService = new DruidService<DruidService.OverlordService>(
zkRootPath + overlordLeaderElectionPath,
DruidService.OverlordService.class
);
coordinatorService = new DruidService<DruidService.CoordinatorService>(
zkRootPath + coordinatorLeaderElectionPath,
DruidService.CoordinatorService.class
);
}
private List<JsonValues> getDataServiceNodes(String type, String name) {
DruidService.CoordinatorService service = coordinatorService.getService();
if (service == null) {
log.warn("coordinator service not found!");
return Collections.emptyList();
}
List<Map<String, Object>> nodes = service.getDataServers();
List<JsonValues> typeNodes = Lists.newArrayList();
for (Map<String, Object> node : nodes) {
if (type.equals(node.get("type"))) {
node.put("used", (Double) node.get("currSize") / (Double) node.get("maxSize"));
node.put("name", name);
typeNodes.add(JsonValues.of(node, "name", "host", "type", "maxSize", "currSize", "used", "tier", "priority"));
}
}
return typeNodes;
}
public List<JsonValues> getRealtimeNodes() {
return getDataServiceNodes("realtime", realtimeName);
}
public List<JsonValues> getHistoricalNodes() {
return getDataServiceNodes("historical", historicalName);
}
public List<JsonValues> getMiddleManagerNodes() {
DruidService.OverlordService service = overlordService.getService();
if (service == null) {
log.warn("overlord service not found!");
return Collections.emptyList();
}
return Lists.transform(
service.getWorkers(), new Function<DruidService.MiddleManager, JsonValues>() {
@Override
public JsonValues apply(DruidService.MiddleManager input) {
return input.toJsonValues();
}
}
);
}
public List<AnnounceNode> getBrokerNodes() {
return getAnnounceNodes(brokerName, null);
}
public List<AnnounceNode> getCoordinatorNodes() {
return getAnnounceNodes(coordinatorName, zkRootPath + coordinatorLeaderElectionPath);
}
public List<AnnounceNode> getOverlordNodes() {
return getAnnounceNodes(overlordName, zkRootPath + overlordLeaderElectionPath);
}
private List<AnnounceNode> getAnnounceNodes(String serviceName, String leaderElectionPath) {
List<AnnounceNode> nodes = Lists.transform(
DCMZkUtils.getZKChildrenContent(zkDiscoveryPath + "/" + serviceName, false),
new Function<String, AnnounceNode>() {
@Override
public AnnounceNode apply(String input) {
Map<String, Object> m = Utils.toMap(input);
AnnounceNode node = new AnnounceNode();
node.host = (String) m.get("address") + ":" + (Integer) m.get("port");
node.name = (String) m.get("name");
node.role = "-";
node.regTime = new DateTime((Long) m.get("registrationTimeUTC")).toString();
node.serviceType = (String) m.get("serviceType");
return node;
}
}
);
String leaderHost = null;
List<String> waitingHosts = Collections.emptyList();
if (leaderElectionPath != null) {
leaderHost = DCMZkUtils.getLeaderContent(leaderElectionPath);
waitingHosts = DCMZkUtils.getZKChildrenContent(leaderElectionPath, false);
}
Map<String, AnnounceNode> nodeMap = Maps.newHashMap();
for (AnnounceNode node : nodes) {
if (node.host.equals(leaderHost)) {
node.role = "leader";
}
nodeMap.put(node.host, node);
}
// Backup nodes won't announce themseleves until them got a chance to be leader,
// we also need to put them in.
for (String host : waitingHosts) {
if (!nodeMap.containsKey(host)) {
AnnounceNode node = new AnnounceNode();
node.host = host;
node.name = serviceName;
node.regTime = "unknown";
node.role = "-";
node.serviceType = "unknown";
nodeMap.put(host, node);
}
}
return Lists.newArrayList(nodeMap.values());
}
public Map<String, List<Event>> getTrendData(Map<String, String> tags, DateTime from, DateTime to) {
return PrometheusUtils.getEvents(EmitMetricsAnalyzer.tableName, tags, from, to);
}
public static void main(String[] args) throws Exception {
Config.init("config");
Resources.init();
DruidInfos infos = Resources.druidInfos;
ObjectMapper om = Resources.jsonMapper;
System.out.println("realtime: " + om.writeValueAsString(infos.getRealtimeNodes()));
System.out.println("broker: " + om.writeValueAsString(infos.getBrokerNodes()));
System.out.println("historical: " + om.writeValueAsString(infos.getHistoricalNodes()));
System.out.println("middle manager: " + om.writeValueAsString(infos.getMiddleManagerNodes()));
System.out.println("coodinator: " + om.writeValueAsString(infos.getCoordinatorNodes()));
System.out.println("overlord: " + om.writeValueAsString(infos.getOverlordNodes()));
Resources.close();
}
}